FasTC: Remove everything except what is required for ASTC support.

This commit is contained in:
bunnei 2018-06-12 15:29:41 -04:00
parent 6171a48b6a
commit 9c4cd7abde
283 changed files with 2 additions and 91793 deletions

3
.gitmodules vendored
View file

@ -1,3 +0,0 @@
[submodule "Windows"]
path = Windows
url = https://github.com/Mokosha/FasTC-MSVCLibs.git

View file

@ -1,162 +0,0 @@
# Copyright 2016 The University of North Carolina at Chapel Hill
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Please send all BUG REPORTS to <pavel@cs.unc.edu>.
# <http://gamma.cs.unc.edu/FasTC/>
IF(NOT "" STREQUAL "${AVPCLLIB_ROOT}")
INCLUDE_DIRECTORIES(${AVPCLLIB_INCLUDE_DIR})
SET(FOUND_NVTT_BPTC_EXPORT TRUE)
ENDIF()
INCLUDE(CheckCXXSourceRuns)
IF( NOT HAS_INLINE_ASSEMBLY AND NOT HAS_INLINE_ASSEMBLY_WITH_FLAGS )
SET( NO_INLINE_ASSEMBLY true )
ENDIF()
# Check to see whether or not our compiler supports atomic operations
IF( ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR
${CMAKE_C_COMPILER_ID} STREQUAL "Clang" )
SET( COMPILER_CLANG True )
ELSEIF( ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" OR
${CMAKE_C_COMPILER_ID} STREQUAL "GNU" )
SET( COMPILER_GNU True )
ENDIF()
IF( COMPILER_CLANG OR COMPILER_GNU )
CHECK_CXX_SOURCE_RUNS("
int main() {
int x = 0;
__sync_fetch_and_add(&x, 1);
return !x;
}"
HAS_GCC_ATOMICS
)
ELSEIF( MSVC )
CHECK_CXX_SOURCE_RUNS("
#include <Windows.h>
int main() {
unsigned int val;
unsigned int *x = (unsigned int *)_aligned_malloc(sizeof(int), 32);
*x = 0;
val = InterlockedIncrement(x);
_aligned_free(x);
return !val;
}"
HAS_MSVC_ATOMICS
)
ENDIF()
IF( HAS_MSVC_ATOMICS OR HAS_GCC_ATOMICS )
SET(HAS_ATOMICS true)
ENDIF()
CONFIGURE_FILE(
"config/BPTCConfig.h.in"
"include/FasTC/BPTCConfig.h"
)
SET(LIBRARY_HEADERS
"include/FasTC/BPTCCompressor.h"
"include/FasTC/Shapes.h"
)
SET( HEADERS
config/BPTCConfig.h.in
src/AnchorTables.h
src/CompressionMode.h
src/RGBAEndpoints.h
src/ParallelStage.h
${LIBRARY_HEADERS}
)
SET( SOURCES
src/Compressor.cpp
src/Decompressor.cpp
src/RGBAEndpoints.cpp
src/ParallelStage.cpp
)
IF( HAS_SSE_41 )
IF ( HAS_SSE_POPCNT )
IF( MSVC )
ADD_DEFINITIONS( /arch:SSE4.2 )
ELSE() #Assume GCC
ADD_DEFINITIONS( -msse4.2 )
ENDIF()
ELSE()
IF( MSVC )
ADD_DEFINITIONS( /arch:SSE4.1 )
ELSE() #Assume GCC
ADD_DEFINITIONS( -msse4.1 )
ENDIF()
ENDIF()
SET( HEADERS
${HEADERS}
src/RGBAEndpointsSIMD.h
src/CompressionModeSIMD.h
)
SET( SOURCES
${SOURCES}
src/CompressorSIMD.cpp
src/RGBAEndpointsSIMD.cpp
)
ENDIF( HAS_SSE_41 )
IF( HAS_INLINE_ASSEMBLY_WITH_FLAGS )
IF( MSVC )
# !FIXME!
ELSE()
ADD_DEFINITIONS( -fasm-blocks )
ENDIF()
ENDIF()
IF(NOT "" STREQUAL "${AVPCLLIB_ROOT}")
SET( SOURCES
${SOURCES}
src/CompressNVTT.cpp
)
ENDIF()
SET(BPTC_INCLUDES_DIR ${FasTC_BINARY_DIR}/BPTCEncoder/include/FasTC)
INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Base/include)
INCLUDE_DIRECTORIES(${FasTC_BINARY_DIR}/Base/include)
INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/BPTCEncoder/include)
INCLUDE_DIRECTORIES(${FasTC_BINARY_DIR}/BPTCEncoder/include)
ADD_LIBRARY( BPTCEncoder
${HEADERS}
${SOURCES}
)
INSTALL(TARGETS BPTCEncoder EXPORT FasTCTargets ARCHIVE DESTINATION lib COMPONENT lib)
INSTALL(
FILES ${LIBRARY_HEADERS} "${BPTC_INCLUDES_DIR}/BPTCConfig.h"
DESTINATION ${INCLUDE_INSTALL_DIR}/FasTC
COMPONENT dev)
TARGET_LINK_LIBRARIES( BPTCEncoder FasTCBase )
IF(NOT "" STREQUAL "${AVPCLLIB_ROOT}")
TARGET_LINK_LIBRARIES( BPTCEncoder avpcl )
ENDIF()

View file

@ -1,30 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
// BPTCConfig.h.in -- This file contains variables that are introduced
// explicitly by the CMake build process.
// Do we have the proper popcnt instruction defined?
#cmakedefine NO_INLINE_ASSEMBLY
#cmakedefine HAS_SSE_POPCNT
#cmakedefine HAS_SSE_41
#cmakedefine HAS_ATOMICS
#cmakedefine HAS_GCC_ATOMICS
#cmakedefine HAS_MSVC_ATOMICS
#cmakedefine FOUND_NVTT_BPTC_EXPORT

View file

@ -1,219 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
// The original lisence from the code available at the following location:
// http://software.intel.com/en-us/vcsource/samples/fast-texture-compression
//
// This code has been modified significantly from the original.
//------------------------------------------------------------------------------
// Copyright 2011 Intel Corporation
// All Rights Reserved
//
// Permission is granted to use, copy, distribute and prepare derivative works
// of this software for any purpose and without fee, provided, that the above
// copyright notice and this statement appear in all copies. Intel makes no
// representations about the suitability of this software for any purpose. THIS
// SOFTWARE IS PROVIDED "AS IS." INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER
// INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR
// INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not assume
// any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
//
//------------------------------------------------------------------------------
#ifndef BPTCENCODER_INCLUDE_BPTCCOMPRESSOR_H_
#define BPTCENCODER_INCLUDE_BPTCCOMPRESSOR_H_
#include "FasTC/CompressionJob.h"
#include "FasTC/Pixel.h"
#include "FasTC/BPTCConfig.h"
#include <iosfwd>
#include <vector>
namespace BPTCC {
// The various available block modes that a BPTC compressor can choose from.
// The enum is specialized to be power-of-two values so that an EBlockMode
// variable can be used as a bit mask.
enum EBlockMode {
eBlockMode_Zero = 1,
eBlockMode_One = 2,
eBlockMode_Two = 4,
eBlockMode_Three = 8,
eBlockMode_Four = 16,
eBlockMode_Five = 32,
eBlockMode_Six = 64,
eBlockMode_Seven = 128
};
// This is the error metric that is applied to our error measurement algorithm
// in order to bias calculation towards results that are more in-line with
// how the Human Visual System works. Uniform error means that each color
// channel is treated equally. For a while, the widely accepted non-uniform
// metric has been to give red 30%, green 59% and blue 11% weight when
// computing the error between two pixels.
enum ErrorMetric {
eErrorMetric_Uniform, // Treats r, g, and b channels equally
eErrorMetric_Nonuniform, // { 0.3, 0.59, 0.11 }
kNumErrorMetrics
};
// A shape consists of an index into the table of shapes and the number
// of partitions that the index corresponds to. Different BPTC modes
// interpret the shape differently and some are even illegal (such as
// having an index >= 16 on mode 0). Hence, each shape corresponds to
// these two variables.
struct Shape {
uint32 m_NumPartitions;
uint32 m_Index;
};
// A shape selection can influence the results of the compressor by choosing
// different modes to compress or not compress. The shape index is a value
// between zero and sixty-four that corresponds to one of the available
// partitioning schemes defined by the BPTC format.
struct ShapeSelection {
// This is the number of valid shapes in m_Shapes
uint32 m_NumShapesToSearch;
// These are the shape indices to use when evaluating shapes.
// I.e. the shapes that the compressor will try to optimize.
Shape m_Shapes[10];
// This is the additional mask to prevent modes once shape selection
// is done. This value is &-ed with m_BlockModes from CompressionSettings
// to determine what the final considered blocks are.
uint32 m_SelectedModes;
// Defaults
ShapeSelection()
: m_NumShapesToSearch(0)
, m_SelectedModes(static_cast<EBlockMode>(0xFF))
{ }
};
// A shape selection function is one that selects a BPTC shape from a given
// block position and pixel array.
typedef ShapeSelection (*ShapeSelectionFn)
(uint32 x, uint32 y, const uint32 pixels[16], const void *userData);
// Compression parameters used to control the BPTC compressor. Each of the
// values has a default, so this is not strictly required to perform
// compression, but some aspects of the compressor can be user-defined or
// overridden.
struct CompressionSettings {
// The shape selection function to use during compression. The default (when
// this variable is set to NULL) is to use the diagonal of the axis-aligned
// bounding box of every partition to estimate the error using that
// partition would accrue. The shape with the least error is then chosen.
// This procedure is done for both two and three partition shapes, and then
// every block mode is still available.
ShapeSelectionFn m_ShapeSelectionFn;
// The user data passed to the shape selection function.
const void *m_ShapeSelectionUserData;
// The block modes that the compressor will consider during compression.
// This variable is a bit mask of EBlockMode values and by default contains
// every mode. This setting can be used to further restrict the search space
// and increase compression times.
uint32 m_BlockModes;
// See the description for ErrorMetric.
ErrorMetric m_ErrorMetric;
// The number of simulated annealing steps to perform per refinement
// iteration. In general, a larger number produces better results. The
// default is set to 50. This metric works on a logarithmic scale -- twice
// the value will double the compute time, but only decrease the error by
// two times a factor.
uint32 m_NumSimulatedAnnealingSteps;
CompressionSettings()
: m_ShapeSelectionFn(NULL)
, m_ShapeSelectionUserData(NULL)
, m_BlockModes(static_cast<EBlockMode>(0xFF))
, m_ErrorMetric(eErrorMetric_Uniform)
, m_NumSimulatedAnnealingSteps(50)
{ }
};
// Retreives a float4 pointer for the r, g, b, a weights for each color
// channel, in that order.
const float *GetErrorMetric(ErrorMetric e);
// Compress the image given as RGBA data to BPTC format. Width and Height are
// the dimensions of the image in pixels.
void Compress(const FasTC::CompressionJob &,
CompressionSettings settings = CompressionSettings());
// Perform a compression while recording all of the choices the compressor
// made into a list of statistics. We can use this to see whether or not
// certain heuristics are working, such as whether or not certain modes are
// being chosen more often than others, etc.
void CompressWithStats(const FasTC::CompressionJob &, std::ostream *logStream,
CompressionSettings settings = CompressionSettings());
#ifdef HAS_SSE_41
// Compress the image given as RGBA data to BPTC format using an algorithm
// optimized for SIMD enabled platforms. Width and Height are the dimensions
// of the image in pixels.
void CompressImageBPTCSIMD(const unsigned char* inBuf, unsigned char* outBuf,
unsigned int width, unsigned int height);
#endif
#ifdef HAS_ATOMICS
// This is a threadsafe version of the compression function that is designed
// to compress a list of textures. If this function is called with the same
// argument from multiple threads, they will work together to compress all of
// the images in the list.
void CompressAtomic(FasTC::CompressionJobList &);
#endif
#ifdef FOUND_NVTT_BPTC_EXPORT
// These functions take the same arguments as Compress and CompressWithStats,
// but they use the NVTT compressor if it was supplied to CMake.
void CompressNVTT(const FasTC::CompressionJob &);
void CompressNVTTWithStats(const FasTC::CompressionJob &,
std::ostream *logStream);
#endif
// A logical BPTC block. Each block has a mode, up to three
// endpoint pairs, a shape, and a per-pixel index to choose
// the proper endpoints.
struct LogicalBlock {
EBlockMode m_Mode;
Shape m_Shape;
FasTC::Pixel m_Endpoints[3][2];
uint32 m_Indices[16];
uint32 m_AlphaIndices[16];
};
// Decompress the data stored into logical blocks
void DecompressLogical(const FasTC::DecompressionJob &,
std::vector<LogicalBlock> *out);
// Decompress the image given as BPTC data to R8G8B8A8 format.
void Decompress(const FasTC::DecompressionJob &);
} // namespace BPTCC
#endif // BPTCENCODER_INCLUDE_BPTCCOMPRESSOR_H_

View file

@ -1,83 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#ifndef BPTCENCODER_INCLUDE_SHAPES_H_
#define BPTCENCODER_INCLUDE_SHAPES_H_
namespace BPTCC {
static const uint32 kNumShapes2 = 64;
static const uint16 kShapeMask2[kNumShapes2] = {
0xcccc, 0x8888, 0xeeee, 0xecc8, 0xc880, 0xfeec, 0xfec8, 0xec80,
0xc800, 0xffec, 0xfe80, 0xe800, 0xffe8, 0xff00, 0xfff0, 0xf000,
0xf710, 0x008e, 0x7100, 0x08ce, 0x008c, 0x7310, 0x3100, 0x8cce,
0x088c, 0x3110, 0x6666, 0x366c, 0x17e8, 0x0ff0, 0x718e, 0x399c,
0xaaaa, 0xf0f0, 0x5a5a, 0x33cc, 0x3c3c, 0x55aa, 0x9696, 0xa55a,
0x73ce, 0x13c8, 0x324c, 0x3bdc, 0x6996, 0xc33c, 0x9966, 0x0660,
0x0272, 0x04e4, 0x4e40, 0x2720, 0xc936, 0x936c, 0x39c6, 0x639c,
0x9336, 0x9cc6, 0x817e, 0xe718, 0xccf0, 0x0fcc, 0x7744, 0xee22
};
static const uint32 kNumShapes3 = 64;
static const uint16 kShapeMask3[kNumShapes3][2] = {
{0xfecc, 0xf600}, {0xffc8, 0x7300}, {0xff90, 0x3310}, {0xecce, 0x00ce},
{0xff00, 0xcc00}, {0xcccc, 0xcc00}, {0xffcc, 0x00cc}, {0xffcc, 0x3300},
{0xff00, 0xf000}, {0xfff0, 0xf000}, {0xfff0, 0xff00}, {0xcccc, 0x8888},
{0xeeee, 0x8888}, {0xeeee, 0xcccc}, {0xffec, 0xec80}, {0x739c, 0x7310},
{0xfec8, 0xc800}, {0x39ce, 0x3100}, {0xfff0, 0xccc0}, {0xfccc, 0x0ccc},
{0xeeee, 0xee00}, {0xff88, 0x7700}, {0xeec0, 0xcc00}, {0x7730, 0x3300},
{0x0cee, 0x00cc}, {0xffcc, 0xfc88}, {0x6ff6, 0x0660}, {0xff60, 0x6600},
{0xcbbc, 0xc88c}, {0xf966, 0xf900}, {0xceec, 0x0cc0}, {0xff10, 0x7310},
{0xff80, 0xec80}, {0xccce, 0x08ce}, {0xeccc, 0xec80}, {0x6666, 0x4444},
{0x0ff0, 0x0f00}, {0x6db6, 0x4924}, {0x6bd6, 0x4294}, {0xcf3c, 0x0c30},
{0xc3fc, 0x03c0}, {0xffaa, 0xff00}, {0xff00, 0x5500}, {0xfcfc, 0xcccc},
{0xcccc, 0x0c0c}, {0xf6f6, 0x6666}, {0xaffa, 0x0ff0}, {0xfff0, 0x5550},
{0xfaaa, 0xf000}, {0xeeee, 0x0e0e}, {0xf8f8, 0x8888}, {0xfff0, 0x9990},
{0xeeee, 0xe00e}, {0x8ff8, 0x8888}, {0xf666, 0xf000}, {0xff00, 0x9900},
{0xff66, 0xff00}, {0xcccc, 0xc00c}, {0xcffc, 0xcccc}, {0xf000, 0x9000},
{0x8888, 0x0808}, {0xfefe, 0xeeee}, {0xfffa, 0xfff0}, {0x7bde, 0x7310}
};
static uint8 GetSubsetForIndex(int idx, const int shapeIdx, const int nSubs) {
int subset = 0;
switch(nSubs) {
case 2:
{
subset = !!((1 << idx) & kShapeMask2[shapeIdx]);
}
break;
case 3:
{
if(1 << idx & kShapeMask3[shapeIdx][0])
subset = 1 + !!((1 << idx) & kShapeMask3[shapeIdx][1]);
else
subset = 0;
}
break;
default:
break;
}
return subset;
}
} // namespace BPTCC
#endif // BPTCENCODER_INCLUDE_SHAPES_H_

View file

@ -1,85 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "FasTC/Shapes.h"
#include <cassert>
static const int kAnchorIdx2[BPTCC::kNumShapes2] = {
15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15,
15, 2, 8, 2, 2, 8, 8, 15,
2 , 8, 2, 2, 8, 8, 2, 2,
15, 15, 6, 8, 2, 8, 15, 15,
2 , 8, 2, 2, 2, 15, 15, 6,
6 , 2, 6, 8, 15, 15, 2, 2,
15, 15, 15, 15, 15, 2, 2, 15
};
static const int kAnchorIdx3[2][BPTCC::kNumShapes3] = {
{3, 3, 15, 15, 8, 3, 15, 15,
8 , 8, 6, 6, 6, 5, 3, 3,
3 , 3, 8, 15, 3, 3, 6, 10,
5 , 8, 8, 6, 8, 5, 15, 15,
8 , 15, 3, 5, 6, 10, 8, 15,
15, 3, 15, 5, 15, 15, 15, 15,
3 , 15, 5, 5, 5, 8, 5, 10,
5 , 10, 8, 13, 15, 12, 3, 3 },
{15, 8, 8, 3, 15, 15, 3, 8,
15 , 15, 15, 15, 15, 15, 15, 8,
15 , 8, 15, 3, 15, 8, 15, 8,
3 , 15, 6, 10, 15, 15, 10, 8,
15 , 3, 15, 10, 10, 8, 9, 10,
6 , 15, 8, 15, 3, 6, 6, 8,
15 , 3, 15, 15, 15, 15, 15, 15,
15 , 15, 15, 15, 3, 15, 15, 8 }
};
namespace BPTCC {
static uint32 GetAnchorIndexForSubset(
int subset, const int shapeIdx, const int nSubsets
) {
int anchorIdx = 0;
switch(subset) {
case 1:
{
if(nSubsets == 2) {
anchorIdx = kAnchorIdx2[shapeIdx];
} else {
anchorIdx = kAnchorIdx3[0][shapeIdx];
}
}
break;
case 2:
{
assert(nSubsets == 3);
anchorIdx = kAnchorIdx3[1][shapeIdx];
}
break;
default:
break;
}
return anchorIdx;
}
} // namespace BPTCC

View file

@ -1,967 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
// The original lisence from the code available at the following location:
// http://software.intel.com/en-us/vcsource/samples/fast-texture-compression
//
// This code has been modified significantly from the original.
//--------------------------------------------------------------------------------------
// Copyright 2011 Intel Corporation
// All Rights Reserved
//
// Permission is granted to use, copy, distribute and prepare derivative works of this
// software for any purpose and without fee, provided, that the above copyright notice
// and this statement appear in all copies. Intel makes no representations about the
// suitability of this software for any purpose. THIS SOFTWARE IS PROVIDED "AS IS."
// INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, AND ALL LIABILITY,
// INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE,
// INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not
// assume any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
//
//--------------------------------------------------------------------------------------
// Each value from 0 to 255 can be exactly interpolated between two other values
// with 7 bit precision. BC7 Mode 5 gives us this precision, so we can use look-up
// tables to speed up this precision by allowing every value to be 1/3 of the way
// between the two colors specified.
/*
UINT nbits = 7;
UINT lastNum = -1;
UINT vals[255];
UINT valIdx = 0;
for(UINT i = 0; i < 256; i++) {
UINT num = (i >> (8 - nbits));
num <<= (8-nbits);
num |= i >> nbits;
if(num != lastNum) {
lastNum = num;
vals[valIdx++] = num;
}
}
for(UINT i = 0; i < 256; i++) {
UINT mindist = 0xFFFFFFFF;
UINT minj = 0, mink = 0;
UINT tableEntry[2] = { 0, 0 };
mindist = 0xFFFFFFFF;
minj = 0, mink = 0;
for(UINT j = 0; j < valIdx; j++) {
for(UINT k = 0; k < valIdx ; k++) {
UINT combo = (43 * vals[j] + 21 * vals[k] + 32) >> 6;
UINT dist = ((i > combo) ? i - combo : combo - i);
if( dist < mindist )
{
mindist = dist;
minj = j;
mink = k;
}
}
}
assert(mindist == 0);
tableEntry[0] = vals[minj];
tableEntry[1] = vals[mink];
wchar_t tableEntryStr[256];
swprintf(tableEntryStr, 256, L"{ 0x%02x, 0x%02x },\n",
tableEntry[0] >> (8 - nbits),
tableEntry[1] >> (8 - nbits)
);
OutputDebugString(tableEntryStr);
}
*/
static unsigned char Optimal7CompressBC7Mode5[256][2] = {
{ 0x00, 0x00 },
{ 0x00, 0x01 },
{ 0x00, 0x03 },
{ 0x00, 0x04 },
{ 0x00, 0x06 },
{ 0x00, 0x07 },
{ 0x00, 0x09 },
{ 0x00, 0x0a },
{ 0x00, 0x0c },
{ 0x00, 0x0d },
{ 0x00, 0x0f },
{ 0x00, 0x10 },
{ 0x00, 0x12 },
{ 0x00, 0x14 },
{ 0x00, 0x15 },
{ 0x00, 0x17 },
{ 0x00, 0x18 },
{ 0x00, 0x1a },
{ 0x00, 0x1b },
{ 0x00, 0x1d },
{ 0x00, 0x1e },
{ 0x00, 0x20 },
{ 0x00, 0x21 },
{ 0x00, 0x23 },
{ 0x00, 0x24 },
{ 0x00, 0x26 },
{ 0x00, 0x27 },
{ 0x00, 0x29 },
{ 0x00, 0x2a },
{ 0x00, 0x2c },
{ 0x00, 0x2d },
{ 0x00, 0x2f },
{ 0x00, 0x30 },
{ 0x00, 0x32 },
{ 0x00, 0x34 },
{ 0x00, 0x35 },
{ 0x00, 0x37 },
{ 0x00, 0x38 },
{ 0x00, 0x3a },
{ 0x00, 0x3b },
{ 0x00, 0x3d },
{ 0x00, 0x3e },
{ 0x00, 0x40 },
{ 0x00, 0x41 },
{ 0x00, 0x42 },
{ 0x00, 0x44 },
{ 0x00, 0x45 },
{ 0x00, 0x47 },
{ 0x00, 0x48 },
{ 0x00, 0x4a },
{ 0x00, 0x4b },
{ 0x00, 0x4d },
{ 0x00, 0x4e },
{ 0x00, 0x50 },
{ 0x00, 0x52 },
{ 0x00, 0x53 },
{ 0x00, 0x55 },
{ 0x00, 0x56 },
{ 0x00, 0x58 },
{ 0x00, 0x59 },
{ 0x00, 0x5b },
{ 0x00, 0x5c },
{ 0x00, 0x5e },
{ 0x00, 0x5f },
{ 0x00, 0x61 },
{ 0x00, 0x62 },
{ 0x00, 0x64 },
{ 0x00, 0x65 },
{ 0x00, 0x67 },
{ 0x00, 0x68 },
{ 0x00, 0x6a },
{ 0x00, 0x6b },
{ 0x00, 0x6d },
{ 0x00, 0x6e },
{ 0x00, 0x70 },
{ 0x00, 0x72 },
{ 0x00, 0x73 },
{ 0x00, 0x75 },
{ 0x00, 0x76 },
{ 0x00, 0x78 },
{ 0x00, 0x79 },
{ 0x00, 0x7b },
{ 0x00, 0x7c },
{ 0x00, 0x7e },
{ 0x00, 0x7f },
{ 0x01, 0x7f },
{ 0x02, 0x7e },
{ 0x03, 0x7e },
{ 0x03, 0x7f },
{ 0x04, 0x7f },
{ 0x05, 0x7e },
{ 0x06, 0x7e },
{ 0x06, 0x7f },
{ 0x07, 0x7f },
{ 0x08, 0x7e },
{ 0x09, 0x7e },
{ 0x09, 0x7f },
{ 0x0a, 0x7f },
{ 0x0b, 0x7e },
{ 0x0c, 0x7e },
{ 0x0c, 0x7f },
{ 0x0d, 0x7f },
{ 0x0e, 0x7e },
{ 0x0f, 0x7d },
{ 0x0f, 0x7f },
{ 0x10, 0x7e },
{ 0x11, 0x7e },
{ 0x11, 0x7f },
{ 0x12, 0x7f },
{ 0x13, 0x7e },
{ 0x14, 0x7e },
{ 0x14, 0x7f },
{ 0x15, 0x7f },
{ 0x16, 0x7e },
{ 0x17, 0x7e },
{ 0x17, 0x7f },
{ 0x18, 0x7f },
{ 0x19, 0x7e },
{ 0x1a, 0x7e },
{ 0x1a, 0x7f },
{ 0x1b, 0x7f },
{ 0x1c, 0x7e },
{ 0x1d, 0x7e },
{ 0x1d, 0x7f },
{ 0x1e, 0x7f },
{ 0x1f, 0x7e },
{ 0x20, 0x7e },
{ 0x20, 0x7f },
{ 0x21, 0x7f },
{ 0x22, 0x7e },
{ 0x23, 0x7e },
{ 0x23, 0x7f },
{ 0x24, 0x7f },
{ 0x25, 0x7e },
{ 0x26, 0x7e },
{ 0x26, 0x7f },
{ 0x27, 0x7f },
{ 0x28, 0x7e },
{ 0x29, 0x7e },
{ 0x29, 0x7f },
{ 0x2a, 0x7f },
{ 0x2b, 0x7e },
{ 0x2c, 0x7e },
{ 0x2c, 0x7f },
{ 0x2d, 0x7f },
{ 0x2e, 0x7e },
{ 0x2f, 0x7d },
{ 0x2f, 0x7f },
{ 0x30, 0x7e },
{ 0x31, 0x7e },
{ 0x31, 0x7f },
{ 0x32, 0x7f },
{ 0x33, 0x7e },
{ 0x34, 0x7e },
{ 0x34, 0x7f },
{ 0x35, 0x7f },
{ 0x36, 0x7e },
{ 0x37, 0x7e },
{ 0x37, 0x7f },
{ 0x38, 0x7f },
{ 0x39, 0x7e },
{ 0x3a, 0x7e },
{ 0x3a, 0x7f },
{ 0x3b, 0x7f },
{ 0x3c, 0x7e },
{ 0x3d, 0x7e },
{ 0x3d, 0x7f },
{ 0x3e, 0x7f },
{ 0x3f, 0x7e },
{ 0x40, 0x7d },
{ 0x40, 0x7e },
{ 0x41, 0x7e },
{ 0x41, 0x7f },
{ 0x42, 0x7f },
{ 0x43, 0x7e },
{ 0x44, 0x7e },
{ 0x44, 0x7f },
{ 0x45, 0x7f },
{ 0x46, 0x7e },
{ 0x47, 0x7e },
{ 0x47, 0x7f },
{ 0x48, 0x7f },
{ 0x49, 0x7e },
{ 0x4a, 0x7e },
{ 0x4a, 0x7f },
{ 0x4b, 0x7f },
{ 0x4c, 0x7e },
{ 0x4d, 0x7d },
{ 0x4d, 0x7f },
{ 0x4e, 0x7e },
{ 0x4f, 0x7e },
{ 0x4f, 0x7f },
{ 0x50, 0x7f },
{ 0x51, 0x7e },
{ 0x52, 0x7e },
{ 0x52, 0x7f },
{ 0x53, 0x7f },
{ 0x54, 0x7e },
{ 0x55, 0x7e },
{ 0x55, 0x7f },
{ 0x56, 0x7f },
{ 0x57, 0x7e },
{ 0x58, 0x7e },
{ 0x58, 0x7f },
{ 0x59, 0x7f },
{ 0x5a, 0x7e },
{ 0x5b, 0x7e },
{ 0x5b, 0x7f },
{ 0x5c, 0x7f },
{ 0x5d, 0x7e },
{ 0x5e, 0x7e },
{ 0x5e, 0x7f },
{ 0x5f, 0x7f },
{ 0x60, 0x7e },
{ 0x61, 0x7e },
{ 0x61, 0x7f },
{ 0x62, 0x7f },
{ 0x63, 0x7e },
{ 0x64, 0x7e },
{ 0x64, 0x7f },
{ 0x65, 0x7f },
{ 0x66, 0x7e },
{ 0x67, 0x7e },
{ 0x67, 0x7f },
{ 0x68, 0x7f },
{ 0x69, 0x7e },
{ 0x6a, 0x7e },
{ 0x6a, 0x7f },
{ 0x6b, 0x7f },
{ 0x6c, 0x7e },
{ 0x6d, 0x7d },
{ 0x6d, 0x7f },
{ 0x6e, 0x7e },
{ 0x6f, 0x7e },
{ 0x6f, 0x7f },
{ 0x70, 0x7f },
{ 0x71, 0x7e },
{ 0x72, 0x7e },
{ 0x72, 0x7f },
{ 0x73, 0x7f },
{ 0x74, 0x7e },
{ 0x75, 0x7e },
{ 0x75, 0x7f },
{ 0x76, 0x7f },
{ 0x77, 0x7e },
{ 0x78, 0x7e },
{ 0x78, 0x7f },
{ 0x79, 0x7f },
{ 0x7a, 0x7e },
{ 0x7b, 0x7e },
{ 0x7b, 0x7f },
{ 0x7c, 0x7f },
{ 0x7d, 0x7e },
{ 0x7e, 0x7e },
{ 0x7e, 0x7f },
{ 0x7f, 0x7f }
};
// For each value, we give the best possible compression range for that value with 5 bits.
// The first value says whether or not it's
// 1 - the midpoint of two other values, or
// 0 - 1/3 of the way in between two other values.
// If the first value is 1 or 2 then the last two values are the range between which the
// value should be interpolated. If the first value is 2, then it should be interpolated
// one third of the way from the second to third value...
//
// The following tables were generated with the following program:
/*
UINT nbits = 5;
UINT lastNum = -1;
UINT vals[255];
UINT valIdx = 0;
for(UINT i = 0; i < 256; i++) {
UINT num = (i >> (8 - nbits));
num <<= (8-nbits);
num |= i >> nbits;
if(num != lastNum) {
lastNum = num;
vals[valIdx++] = num;
}
}
for(UINT i = 0; i < 256; i++) {
UINT mindist = 0xFFFFFFFF;
UINT minj = 0, mink = 0;
UINT tableEntry[2][4] = { {1, 0, 0, 0xFFFFFFFF}, {0, 0, 0, 0xFFFFFFFF} };
for(UINT j = 0; j < valIdx; j++) {
for(UINT k = j; k < valIdx ; k++) {
UINT combo = (vals[j] + vals[k]) / 2;
UINT dist = ((i > combo) ? i - combo : combo - i);
if( dist < mindist )
{
mindist = dist;
minj = j;
mink = k;
}
}
}
tableEntry[0][1] = vals[minj];
tableEntry[0][2] = vals[mink];
tableEntry[0][3] = mindist;
mindist = 0xFFFFFFFF;
minj = 0, mink = 0;
for(UINT j = 0; j < valIdx; j++) {
for(UINT k = j; k < valIdx ; k++) {
UINT combo = (2 * vals[j] + vals[k]) / 3;
UINT dist = ((i > combo) ? i - combo : combo - i);
if( dist < mindist )
{
mindist = dist;
minj = j;
mink = k;
}
}
}
tableEntry[1][1] = vals[minj];
tableEntry[1][2] = vals[mink];
tableEntry[1][3] = mindist;
wchar_t tableEntryStr[256];
if(tableEntry[1][3] > tableEntry[0][3]) {
swprintf(tableEntryStr, 256, L"{ { %d, 0x%02x, 0x%02x }, { %d, 0x%02x, 0x%02x } },\n",
tableEntry[0][0],
tableEntry[0][1] >> (8 - nbits),
tableEntry[0][2] >> (8 - nbits),
tableEntry[1][0],
tableEntry[1][1] >> (8 - nbits),
tableEntry[1][2] >> (8 - nbits)
);
}
else {
swprintf(tableEntryStr, 256, L"{ { %d, 0x%02x, 0x%02x }, { %d, 0x%02x, 0x%02x } },\n",
tableEntry[1][0],
tableEntry[1][1] >> (8 - nbits),
tableEntry[1][2] >> (8 - nbits),
tableEntry[0][0],
tableEntry[0][1] >> (8 - nbits),
tableEntry[0][2] >> (8 - nbits)
);
}
OutputDebugString(tableEntryStr);
}
static unsigned char Optimal5CompressDXT1[256][2][3] = {
{ { 0, 0x00, 0x00 }, { 1, 0x00, 0x00 } },
{ { 0, 0x00, 0x00 }, { 1, 0x00, 0x00 } },
{ { 0, 0x00, 0x01 }, { 1, 0x00, 0x00 } },
{ { 0, 0x00, 0x01 }, { 1, 0x00, 0x01 } },
{ { 1, 0x00, 0x01 }, { 0, 0x00, 0x02 } },
{ { 0, 0x00, 0x02 }, { 1, 0x00, 0x01 } },
{ { 0, 0x00, 0x02 }, { 1, 0x00, 0x01 } },
{ { 0, 0x00, 0x03 }, { 1, 0x00, 0x02 } },
{ { 0, 0x00, 0x03 }, { 1, 0x00, 0x02 } },
{ { 0, 0x00, 0x03 }, { 1, 0x00, 0x02 } },
{ { 0, 0x01, 0x02 }, { 1, 0x00, 0x02 } },
{ { 0, 0x00, 0x04 }, { 1, 0x00, 0x03 } },
{ { 1, 0x00, 0x03 }, { 0, 0x00, 0x04 } },
{ { 0, 0x00, 0x05 }, { 1, 0x00, 0x03 } },
{ { 0, 0x00, 0x05 }, { 1, 0x00, 0x03 } },
{ { 0, 0x00, 0x06 }, { 1, 0x00, 0x04 } },
{ { 0, 0x00, 0x06 }, { 1, 0x00, 0x04 } },
{ { 0, 0x00, 0x06 }, { 1, 0x00, 0x04 } },
{ { 0, 0x02, 0x03 }, { 1, 0x00, 0x04 } },
{ { 0, 0x00, 0x07 }, { 1, 0x00, 0x05 } },
{ { 1, 0x00, 0x05 }, { 0, 0x00, 0x07 } },
{ { 0, 0x01, 0x06 }, { 1, 0x00, 0x05 } },
{ { 0, 0x00, 0x08 }, { 1, 0x00, 0x05 } },
{ { 0, 0x00, 0x08 }, { 1, 0x00, 0x06 } },
{ { 0, 0x00, 0x09 }, { 1, 0x00, 0x06 } },
{ { 0, 0x00, 0x09 }, { 1, 0x00, 0x06 } },
{ { 0, 0x00, 0x0a }, { 1, 0x00, 0x06 } },
{ { 0, 0x00, 0x0a }, { 1, 0x00, 0x07 } },
{ { 1, 0x00, 0x07 }, { 0, 0x00, 0x0a } },
{ { 0, 0x02, 0x07 }, { 1, 0x00, 0x07 } },
{ { 0, 0x00, 0x0b }, { 1, 0x00, 0x07 } },
{ { 0, 0x00, 0x0b }, { 1, 0x01, 0x07 } },
{ { 0, 0x01, 0x0a }, { 1, 0x01, 0x07 } },
{ { 0, 0x00, 0x0c }, { 1, 0x00, 0x08 } },
{ { 0, 0x00, 0x0c }, { 1, 0x00, 0x08 } },
{ { 0, 0x00, 0x0d }, { 1, 0x02, 0x07 } },
{ { 1, 0x02, 0x07 }, { 0, 0x00, 0x0d } },
{ { 1, 0x00, 0x09 }, { 0, 0x00, 0x0e } },
{ { 0, 0x00, 0x0e }, { 1, 0x00, 0x09 } },
{ { 0, 0x00, 0x0e }, { 1, 0x03, 0x07 } },
{ { 0, 0x02, 0x0b }, { 1, 0x03, 0x07 } },
{ { 0, 0x00, 0x0f }, { 1, 0x00, 0x0a } },
{ { 0, 0x00, 0x0f }, { 1, 0x00, 0x0a } },
{ { 0, 0x01, 0x0e }, { 1, 0x00, 0x0a } },
{ { 0, 0x00, 0x10 }, { 1, 0x00, 0x0b } },
{ { 1, 0x00, 0x0b }, { 0, 0x00, 0x10 } },
{ { 0, 0x00, 0x11 }, { 1, 0x00, 0x0b } },
{ { 0, 0x00, 0x11 }, { 1, 0x00, 0x0b } },
{ { 0, 0x00, 0x12 }, { 1, 0x00, 0x0c } },
{ { 0, 0x00, 0x12 }, { 1, 0x00, 0x0c } },
{ { 0, 0x00, 0x12 }, { 1, 0x00, 0x0c } },
{ { 0, 0x02, 0x0f }, { 1, 0x00, 0x0c } },
{ { 0, 0x00, 0x13 }, { 1, 0x00, 0x0d } },
{ { 1, 0x00, 0x0d }, { 0, 0x00, 0x13 } },
{ { 0, 0x01, 0x12 }, { 1, 0x00, 0x0d } },
{ { 0, 0x00, 0x14 }, { 1, 0x00, 0x0d } },
{ { 0, 0x00, 0x14 }, { 1, 0x00, 0x0e } },
{ { 0, 0x00, 0x15 }, { 1, 0x00, 0x0e } },
{ { 0, 0x00, 0x15 }, { 1, 0x00, 0x0e } },
{ { 0, 0x00, 0x16 }, { 1, 0x00, 0x0e } },
{ { 0, 0x00, 0x16 }, { 1, 0x00, 0x0f } },
{ { 1, 0x00, 0x0f }, { 0, 0x00, 0x16 } },
{ { 0, 0x02, 0x13 }, { 1, 0x00, 0x0f } },
{ { 0, 0x00, 0x17 }, { 1, 0x00, 0x0f } },
{ { 0, 0x00, 0x17 }, { 1, 0x01, 0x0f } },
{ { 0, 0x01, 0x16 }, { 1, 0x01, 0x0f } },
{ { 0, 0x00, 0x18 }, { 1, 0x00, 0x10 } },
{ { 0, 0x00, 0x18 }, { 1, 0x00, 0x10 } },
{ { 0, 0x00, 0x19 }, { 1, 0x02, 0x0f } },
{ { 1, 0x02, 0x0f }, { 0, 0x00, 0x19 } },
{ { 1, 0x00, 0x11 }, { 0, 0x00, 0x1a } },
{ { 0, 0x00, 0x1a }, { 1, 0x00, 0x11 } },
{ { 0, 0x00, 0x1a }, { 1, 0x03, 0x0f } },
{ { 0, 0x02, 0x17 }, { 1, 0x03, 0x0f } },
{ { 0, 0x00, 0x1b }, { 1, 0x00, 0x12 } },
{ { 0, 0x00, 0x1b }, { 1, 0x00, 0x12 } },
{ { 0, 0x01, 0x1a }, { 1, 0x00, 0x12 } },
{ { 0, 0x00, 0x1c }, { 1, 0x00, 0x13 } },
{ { 1, 0x00, 0x13 }, { 0, 0x00, 0x1c } },
{ { 0, 0x00, 0x1d }, { 1, 0x00, 0x13 } },
{ { 0, 0x00, 0x1d }, { 1, 0x00, 0x13 } },
{ { 0, 0x00, 0x1e }, { 1, 0x00, 0x14 } },
{ { 0, 0x00, 0x1e }, { 1, 0x00, 0x14 } },
{ { 0, 0x00, 0x1e }, { 1, 0x00, 0x14 } },
{ { 0, 0x02, 0x1b }, { 1, 0x00, 0x14 } },
{ { 0, 0x00, 0x1f }, { 1, 0x00, 0x15 } },
{ { 1, 0x00, 0x15 }, { 0, 0x00, 0x1f } },
{ { 0, 0x01, 0x1e }, { 1, 0x00, 0x15 } },
{ { 0, 0x04, 0x18 }, { 1, 0x00, 0x15 } },
{ { 0, 0x01, 0x1f }, { 1, 0x00, 0x16 } },
{ { 0, 0x01, 0x1f }, { 1, 0x00, 0x16 } },
{ { 0, 0x01, 0x1f }, { 1, 0x00, 0x16 } },
{ { 0, 0x02, 0x1e }, { 1, 0x00, 0x16 } },
{ { 0, 0x02, 0x1e }, { 1, 0x00, 0x17 } },
{ { 1, 0x00, 0x17 }, { 0, 0x02, 0x1e } },
{ { 0, 0x02, 0x1f }, { 1, 0x00, 0x17 } },
{ { 0, 0x04, 0x1b }, { 1, 0x00, 0x17 } },
{ { 0, 0x03, 0x1e }, { 1, 0x01, 0x17 } },
{ { 0, 0x03, 0x1e }, { 1, 0x01, 0x17 } },
{ { 0, 0x04, 0x1c }, { 1, 0x00, 0x18 } },
{ { 0, 0x03, 0x1f }, { 1, 0x00, 0x18 } },
{ { 0, 0x03, 0x1f }, { 1, 0x02, 0x17 } },
{ { 1, 0x02, 0x17 }, { 0, 0x03, 0x1f } },
{ { 1, 0x00, 0x19 }, { 0, 0x04, 0x1e } },
{ { 0, 0x04, 0x1e }, { 1, 0x00, 0x19 } },
{ { 0, 0x04, 0x1e }, { 1, 0x03, 0x17 } },
{ { 0, 0x06, 0x1b }, { 1, 0x03, 0x17 } },
{ { 0, 0x04, 0x1f }, { 1, 0x00, 0x1a } },
{ { 0, 0x04, 0x1f }, { 1, 0x00, 0x1a } },
{ { 0, 0x05, 0x1e }, { 1, 0x00, 0x1a } },
{ { 0, 0x08, 0x18 }, { 1, 0x00, 0x1b } },
{ { 1, 0x00, 0x1b }, { 0, 0x05, 0x1f } },
{ { 0, 0x05, 0x1f }, { 1, 0x00, 0x1b } },
{ { 0, 0x05, 0x1f }, { 1, 0x00, 0x1b } },
{ { 0, 0x06, 0x1e }, { 1, 0x00, 0x1c } },
{ { 0, 0x06, 0x1e }, { 1, 0x00, 0x1c } },
{ { 0, 0x06, 0x1e }, { 1, 0x00, 0x1c } },
{ { 0, 0x06, 0x1f }, { 1, 0x00, 0x1c } },
{ { 0, 0x08, 0x1b }, { 1, 0x00, 0x1d } },
{ { 1, 0x00, 0x1d }, { 0, 0x07, 0x1e } },
{ { 0, 0x07, 0x1e }, { 1, 0x00, 0x1d } },
{ { 0, 0x08, 0x1c }, { 1, 0x00, 0x1d } },
{ { 0, 0x07, 0x1f }, { 1, 0x00, 0x1e } },
{ { 0, 0x07, 0x1f }, { 1, 0x00, 0x1e } },
{ { 0, 0x07, 0x1f }, { 1, 0x00, 0x1e } },
{ { 0, 0x08, 0x1e }, { 1, 0x00, 0x1e } },
{ { 0, 0x08, 0x1e }, { 1, 0x00, 0x1f } },
{ { 1, 0x00, 0x1f }, { 0, 0x08, 0x1e } },
{ { 0, 0x0a, 0x1b }, { 1, 0x00, 0x1f } },
{ { 0, 0x08, 0x1f }, { 1, 0x00, 0x1f } },
{ { 0, 0x08, 0x1f }, { 1, 0x01, 0x1f } },
{ { 0, 0x09, 0x1e }, { 1, 0x01, 0x1f } },
{ { 0, 0x0c, 0x18 }, { 1, 0x04, 0x1c } },
{ { 0, 0x09, 0x1f }, { 1, 0x04, 0x1c } },
{ { 0, 0x09, 0x1f }, { 1, 0x02, 0x1f } },
{ { 1, 0x02, 0x1f }, { 0, 0x09, 0x1f } },
{ { 1, 0x04, 0x1d }, { 0, 0x0a, 0x1e } },
{ { 0, 0x0a, 0x1e }, { 1, 0x04, 0x1d } },
{ { 0, 0x0a, 0x1e }, { 1, 0x03, 0x1f } },
{ { 0, 0x0a, 0x1f }, { 1, 0x03, 0x1f } },
{ { 0, 0x0c, 0x1b }, { 1, 0x04, 0x1e } },
{ { 0, 0x0b, 0x1e }, { 1, 0x04, 0x1e } },
{ { 0, 0x0b, 0x1e }, { 1, 0x04, 0x1e } },
{ { 0, 0x0c, 0x1c }, { 1, 0x04, 0x1f } },
{ { 1, 0x04, 0x1f }, { 0, 0x0b, 0x1f } },
{ { 0, 0x0b, 0x1f }, { 1, 0x04, 0x1f } },
{ { 0, 0x0b, 0x1f }, { 1, 0x04, 0x1f } },
{ { 0, 0x0c, 0x1e }, { 1, 0x05, 0x1f } },
{ { 0, 0x0c, 0x1e }, { 1, 0x05, 0x1f } },
{ { 0, 0x0c, 0x1e }, { 1, 0x05, 0x1f } },
{ { 0, 0x0e, 0x1b }, { 1, 0x05, 0x1f } },
{ { 0, 0x0c, 0x1f }, { 1, 0x06, 0x1f } },
{ { 1, 0x06, 0x1f }, { 0, 0x0c, 0x1f } },
{ { 0, 0x0d, 0x1e }, { 1, 0x06, 0x1f } },
{ { 0, 0x10, 0x18 }, { 1, 0x06, 0x1f } },
{ { 0, 0x0d, 0x1f }, { 1, 0x07, 0x1f } },
{ { 0, 0x0d, 0x1f }, { 1, 0x07, 0x1f } },
{ { 0, 0x0d, 0x1f }, { 1, 0x07, 0x1f } },
{ { 0, 0x0e, 0x1e }, { 1, 0x07, 0x1f } },
{ { 0, 0x0e, 0x1e }, { 1, 0x08, 0x1f } },
{ { 1, 0x08, 0x1f }, { 0, 0x0e, 0x1e } },
{ { 0, 0x0e, 0x1f }, { 1, 0x08, 0x1f } },
{ { 0, 0x10, 0x1b }, { 1, 0x08, 0x1f } },
{ { 0, 0x0f, 0x1e }, { 1, 0x09, 0x1f } },
{ { 0, 0x0f, 0x1e }, { 1, 0x09, 0x1f } },
{ { 0, 0x10, 0x1c }, { 1, 0x0c, 0x1c } },
{ { 0, 0x0f, 0x1f }, { 1, 0x0c, 0x1c } },
{ { 0, 0x0f, 0x1f }, { 1, 0x0a, 0x1f } },
{ { 1, 0x0a, 0x1f }, { 0, 0x0f, 0x1f } },
{ { 1, 0x0c, 0x1d }, { 0, 0x10, 0x1e } },
{ { 0, 0x10, 0x1e }, { 1, 0x0c, 0x1d } },
{ { 0, 0x10, 0x1e }, { 1, 0x0b, 0x1f } },
{ { 0, 0x12, 0x1b }, { 1, 0x0b, 0x1f } },
{ { 0, 0x10, 0x1f }, { 1, 0x0c, 0x1e } },
{ { 0, 0x10, 0x1f }, { 1, 0x0c, 0x1e } },
{ { 0, 0x11, 0x1e }, { 1, 0x0c, 0x1e } },
{ { 0, 0x14, 0x18 }, { 1, 0x0c, 0x1f } },
{ { 1, 0x0c, 0x1f }, { 0, 0x11, 0x1f } },
{ { 0, 0x11, 0x1f }, { 1, 0x0c, 0x1f } },
{ { 0, 0x11, 0x1f }, { 1, 0x0c, 0x1f } },
{ { 0, 0x12, 0x1e }, { 1, 0x0d, 0x1f } },
{ { 0, 0x12, 0x1e }, { 1, 0x0d, 0x1f } },
{ { 0, 0x12, 0x1e }, { 1, 0x0d, 0x1f } },
{ { 0, 0x12, 0x1f }, { 1, 0x0d, 0x1f } },
{ { 0, 0x14, 0x1b }, { 1, 0x0e, 0x1f } },
{ { 1, 0x0e, 0x1f }, { 0, 0x13, 0x1e } },
{ { 0, 0x13, 0x1e }, { 1, 0x0e, 0x1f } },
{ { 0, 0x14, 0x1c }, { 1, 0x0e, 0x1f } },
{ { 0, 0x13, 0x1f }, { 1, 0x0f, 0x1f } },
{ { 0, 0x13, 0x1f }, { 1, 0x0f, 0x1f } },
{ { 0, 0x13, 0x1f }, { 1, 0x0f, 0x1f } },
{ { 0, 0x14, 0x1e }, { 1, 0x0f, 0x1f } },
{ { 0, 0x14, 0x1e }, { 1, 0x10, 0x1f } },
{ { 1, 0x10, 0x1f }, { 0, 0x14, 0x1e } },
{ { 0, 0x16, 0x1b }, { 1, 0x10, 0x1f } },
{ { 0, 0x14, 0x1f }, { 1, 0x10, 0x1f } },
{ { 0, 0x14, 0x1f }, { 1, 0x11, 0x1f } },
{ { 0, 0x15, 0x1e }, { 1, 0x11, 0x1f } },
{ { 0, 0x18, 0x18 }, { 1, 0x14, 0x1c } },
{ { 0, 0x15, 0x1f }, { 1, 0x14, 0x1c } },
{ { 0, 0x15, 0x1f }, { 1, 0x12, 0x1f } },
{ { 1, 0x12, 0x1f }, { 0, 0x15, 0x1f } },
{ { 1, 0x14, 0x1d }, { 0, 0x16, 0x1e } },
{ { 0, 0x16, 0x1e }, { 1, 0x14, 0x1d } },
{ { 0, 0x16, 0x1e }, { 1, 0x13, 0x1f } },
{ { 0, 0x16, 0x1f }, { 1, 0x13, 0x1f } },
{ { 0, 0x18, 0x1b }, { 1, 0x14, 0x1e } },
{ { 0, 0x17, 0x1e }, { 1, 0x14, 0x1e } },
{ { 0, 0x17, 0x1e }, { 1, 0x14, 0x1e } },
{ { 0, 0x18, 0x1c }, { 1, 0x14, 0x1f } },
{ { 1, 0x14, 0x1f }, { 0, 0x17, 0x1f } },
{ { 0, 0x17, 0x1f }, { 1, 0x14, 0x1f } },
{ { 0, 0x17, 0x1f }, { 1, 0x14, 0x1f } },
{ { 0, 0x18, 0x1e }, { 1, 0x15, 0x1f } },
{ { 0, 0x18, 0x1e }, { 1, 0x15, 0x1f } },
{ { 0, 0x18, 0x1e }, { 1, 0x15, 0x1f } },
{ { 0, 0x1a, 0x1b }, { 1, 0x15, 0x1f } },
{ { 0, 0x18, 0x1f }, { 1, 0x16, 0x1f } },
{ { 1, 0x16, 0x1f }, { 0, 0x18, 0x1f } },
{ { 0, 0x19, 0x1e }, { 1, 0x16, 0x1f } },
{ { 0, 0x19, 0x1e }, { 1, 0x16, 0x1f } },
{ { 0, 0x19, 0x1f }, { 1, 0x17, 0x1f } },
{ { 0, 0x19, 0x1f }, { 1, 0x17, 0x1f } },
{ { 0, 0x19, 0x1f }, { 1, 0x17, 0x1f } },
{ { 0, 0x1a, 0x1e }, { 1, 0x17, 0x1f } },
{ { 0, 0x1a, 0x1e }, { 1, 0x18, 0x1f } },
{ { 1, 0x18, 0x1f }, { 0, 0x1a, 0x1e } },
{ { 0, 0x1a, 0x1f }, { 1, 0x18, 0x1f } },
{ { 0, 0x1a, 0x1f }, { 1, 0x18, 0x1f } },
{ { 0, 0x1b, 0x1e }, { 1, 0x19, 0x1f } },
{ { 0, 0x1b, 0x1e }, { 1, 0x19, 0x1f } },
{ { 0, 0x1c, 0x1c }, { 1, 0x1c, 0x1c } },
{ { 0, 0x1b, 0x1f }, { 1, 0x1c, 0x1c } },
{ { 0, 0x1b, 0x1f }, { 1, 0x1a, 0x1f } },
{ { 1, 0x1a, 0x1f }, { 0, 0x1b, 0x1f } },
{ { 1, 0x1c, 0x1d }, { 0, 0x1c, 0x1e } },
{ { 0, 0x1c, 0x1e }, { 1, 0x1c, 0x1d } },
{ { 0, 0x1c, 0x1e }, { 1, 0x1b, 0x1f } },
{ { 1, 0x1b, 0x1f }, { 0, 0x1c, 0x1f } },
{ { 0, 0x1c, 0x1f }, { 1, 0x1c, 0x1e } },
{ { 0, 0x1c, 0x1f }, { 1, 0x1c, 0x1e } },
{ { 0, 0x1d, 0x1e }, { 1, 0x1c, 0x1e } },
{ { 0, 0x1d, 0x1e }, { 1, 0x1c, 0x1f } },
{ { 1, 0x1c, 0x1f }, { 0, 0x1d, 0x1f } },
{ { 0, 0x1d, 0x1f }, { 1, 0x1c, 0x1f } },
{ { 0, 0x1d, 0x1f }, { 1, 0x1c, 0x1f } },
{ { 0, 0x1e, 0x1e }, { 1, 0x1d, 0x1f } },
{ { 0, 0x1e, 0x1e }, { 1, 0x1d, 0x1f } },
{ { 0, 0x1e, 0x1e }, { 1, 0x1d, 0x1f } },
{ { 0, 0x1e, 0x1f }, { 1, 0x1d, 0x1f } },
{ { 0, 0x1e, 0x1f }, { 1, 0x1e, 0x1f } },
{ { 1, 0x1e, 0x1f }, { 0, 0x1e, 0x1f } },
{ { 1, 0x1e, 0x1f }, { 0, 0x1e, 0x1f } },
{ { 0, 0x1f, 0x1f }, { 1, 0x1e, 0x1f } },
{ { 0, 0x1f, 0x1f }, { 1, 0x1f, 0x1f } },
{ { 0, 0x1f, 0x1f }, { 1, 0x1f, 0x1f } }
};
*/
static unsigned char Optimal6CompressDXT1[256][2][3] = {
{ { 0, 0x00, 0x00 }, { 1, 0x00, 0x00 } },
{ { 0, 0x00, 0x01 }, { 1, 0x00, 0x00 } },
{ { 0, 0x00, 0x02 }, { 1, 0x00, 0x01 } },
{ { 0, 0x00, 0x02 }, { 1, 0x00, 0x01 } },
{ { 0, 0x00, 0x03 }, { 1, 0x00, 0x02 } },
{ { 0, 0x00, 0x04 }, { 1, 0x00, 0x02 } },
{ { 0, 0x00, 0x05 }, { 1, 0x00, 0x03 } },
{ { 0, 0x00, 0x05 }, { 1, 0x00, 0x03 } },
{ { 0, 0x00, 0x06 }, { 1, 0x00, 0x04 } },
{ { 0, 0x00, 0x07 }, { 1, 0x00, 0x04 } },
{ { 0, 0x00, 0x08 }, { 1, 0x00, 0x05 } },
{ { 0, 0x00, 0x08 }, { 1, 0x00, 0x05 } },
{ { 0, 0x00, 0x09 }, { 1, 0x00, 0x06 } },
{ { 0, 0x00, 0x0a }, { 1, 0x00, 0x06 } },
{ { 0, 0x00, 0x0b }, { 1, 0x00, 0x07 } },
{ { 0, 0x00, 0x0b }, { 1, 0x00, 0x07 } },
{ { 0, 0x00, 0x0c }, { 1, 0x00, 0x08 } },
{ { 0, 0x00, 0x0d }, { 1, 0x00, 0x08 } },
{ { 0, 0x00, 0x0e }, { 1, 0x00, 0x09 } },
{ { 0, 0x00, 0x0e }, { 1, 0x00, 0x09 } },
{ { 0, 0x00, 0x0f }, { 1, 0x00, 0x0a } },
{ { 0, 0x00, 0x10 }, { 1, 0x00, 0x0a } },
{ { 0, 0x01, 0x0f }, { 1, 0x00, 0x0b } },
{ { 0, 0x00, 0x11 }, { 1, 0x00, 0x0b } },
{ { 0, 0x00, 0x12 }, { 1, 0x00, 0x0c } },
{ { 0, 0x00, 0x13 }, { 1, 0x00, 0x0c } },
{ { 0, 0x03, 0x0e }, { 1, 0x00, 0x0d } },
{ { 0, 0x00, 0x14 }, { 1, 0x00, 0x0d } },
{ { 0, 0x00, 0x15 }, { 1, 0x00, 0x0e } },
{ { 0, 0x00, 0x16 }, { 1, 0x00, 0x0e } },
{ { 0, 0x04, 0x0f }, { 1, 0x00, 0x0f } },
{ { 0, 0x00, 0x17 }, { 1, 0x00, 0x0f } },
{ { 0, 0x00, 0x18 }, { 1, 0x00, 0x10 } },
{ { 0, 0x00, 0x19 }, { 1, 0x00, 0x10 } },
{ { 0, 0x06, 0x0e }, { 1, 0x00, 0x11 } },
{ { 0, 0x00, 0x1a }, { 1, 0x00, 0x11 } },
{ { 0, 0x00, 0x1b }, { 1, 0x00, 0x12 } },
{ { 0, 0x00, 0x1c }, { 1, 0x00, 0x12 } },
{ { 0, 0x07, 0x0f }, { 1, 0x00, 0x13 } },
{ { 0, 0x00, 0x1d }, { 1, 0x00, 0x13 } },
{ { 0, 0x00, 0x1e }, { 1, 0x00, 0x14 } },
{ { 0, 0x00, 0x1f }, { 1, 0x00, 0x14 } },
{ { 0, 0x09, 0x0e }, { 1, 0x00, 0x15 } },
{ { 0, 0x00, 0x20 }, { 1, 0x00, 0x15 } },
{ { 0, 0x00, 0x21 }, { 1, 0x00, 0x16 } },
{ { 0, 0x02, 0x1e }, { 1, 0x00, 0x16 } },
{ { 0, 0x00, 0x22 }, { 1, 0x00, 0x17 } },
{ { 0, 0x00, 0x23 }, { 1, 0x00, 0x17 } },
{ { 0, 0x00, 0x24 }, { 1, 0x00, 0x18 } },
{ { 0, 0x03, 0x1f }, { 1, 0x00, 0x18 } },
{ { 0, 0x00, 0x25 }, { 1, 0x00, 0x19 } },
{ { 0, 0x00, 0x26 }, { 1, 0x00, 0x19 } },
{ { 0, 0x00, 0x27 }, { 1, 0x00, 0x1a } },
{ { 0, 0x05, 0x1e }, { 1, 0x00, 0x1a } },
{ { 0, 0x00, 0x28 }, { 1, 0x00, 0x1b } },
{ { 0, 0x00, 0x29 }, { 1, 0x00, 0x1b } },
{ { 0, 0x00, 0x2a }, { 1, 0x00, 0x1c } },
{ { 0, 0x06, 0x1f }, { 1, 0x00, 0x1c } },
{ { 0, 0x00, 0x2b }, { 1, 0x00, 0x1d } },
{ { 0, 0x00, 0x2c }, { 1, 0x00, 0x1d } },
{ { 0, 0x00, 0x2d }, { 1, 0x00, 0x1e } },
{ { 0, 0x08, 0x1e }, { 1, 0x00, 0x1e } },
{ { 0, 0x00, 0x2e }, { 1, 0x00, 0x1f } },
{ { 0, 0x00, 0x2f }, { 1, 0x00, 0x1f } },
{ { 0, 0x01, 0x2e }, { 1, 0x01, 0x1f } },
{ { 0, 0x00, 0x30 }, { 1, 0x00, 0x20 } },
{ { 0, 0x00, 0x31 }, { 1, 0x02, 0x1f } },
{ { 0, 0x00, 0x32 }, { 1, 0x00, 0x21 } },
{ { 0, 0x02, 0x2f }, { 1, 0x03, 0x1f } },
{ { 0, 0x00, 0x33 }, { 1, 0x00, 0x22 } },
{ { 0, 0x00, 0x34 }, { 1, 0x04, 0x1f } },
{ { 0, 0x00, 0x35 }, { 1, 0x00, 0x23 } },
{ { 0, 0x04, 0x2e }, { 1, 0x05, 0x1f } },
{ { 0, 0x00, 0x36 }, { 1, 0x00, 0x24 } },
{ { 0, 0x00, 0x37 }, { 1, 0x06, 0x1f } },
{ { 0, 0x00, 0x38 }, { 1, 0x00, 0x25 } },
{ { 0, 0x05, 0x2f }, { 1, 0x07, 0x1f } },
{ { 0, 0x00, 0x39 }, { 1, 0x00, 0x26 } },
{ { 0, 0x00, 0x3a }, { 1, 0x08, 0x1f } },
{ { 0, 0x00, 0x3b }, { 1, 0x00, 0x27 } },
{ { 0, 0x07, 0x2e }, { 1, 0x09, 0x1f } },
{ { 0, 0x00, 0x3c }, { 1, 0x00, 0x28 } },
{ { 0, 0x00, 0x3d }, { 1, 0x0a, 0x1f } },
{ { 0, 0x00, 0x3e }, { 1, 0x00, 0x29 } },
{ { 0, 0x08, 0x2f }, { 1, 0x0b, 0x1f } },
{ { 0, 0x00, 0x3f }, { 1, 0x00, 0x2a } },
{ { 0, 0x01, 0x3e }, { 1, 0x0c, 0x1f } },
{ { 0, 0x01, 0x3f }, { 1, 0x00, 0x2b } },
{ { 0, 0x0a, 0x2e }, { 1, 0x0d, 0x1f } },
{ { 0, 0x02, 0x3e }, { 1, 0x00, 0x2c } },
{ { 0, 0x02, 0x3f }, { 1, 0x0e, 0x1f } },
{ { 0, 0x03, 0x3e }, { 1, 0x00, 0x2d } },
{ { 0, 0x0b, 0x2f }, { 1, 0x0f, 0x1f } },
{ { 0, 0x03, 0x3f }, { 1, 0x00, 0x2e } },
{ { 0, 0x04, 0x3e }, { 1, 0x00, 0x2e } },
{ { 0, 0x04, 0x3f }, { 1, 0x00, 0x2f } },
{ { 0, 0x0d, 0x2e }, { 1, 0x00, 0x2f } },
{ { 0, 0x05, 0x3e }, { 1, 0x00, 0x30 } },
{ { 0, 0x05, 0x3f }, { 1, 0x00, 0x30 } },
{ { 0, 0x06, 0x3e }, { 1, 0x00, 0x31 } },
{ { 0, 0x0e, 0x2f }, { 1, 0x00, 0x31 } },
{ { 0, 0x06, 0x3f }, { 1, 0x00, 0x32 } },
{ { 0, 0x07, 0x3e }, { 1, 0x00, 0x32 } },
{ { 0, 0x07, 0x3f }, { 1, 0x00, 0x33 } },
{ { 0, 0x10, 0x2d }, { 1, 0x00, 0x33 } },
{ { 0, 0x08, 0x3e }, { 1, 0x00, 0x34 } },
{ { 0, 0x08, 0x3f }, { 1, 0x00, 0x34 } },
{ { 0, 0x09, 0x3e }, { 1, 0x00, 0x35 } },
{ { 0, 0x10, 0x30 }, { 1, 0x00, 0x35 } },
{ { 0, 0x09, 0x3f }, { 1, 0x00, 0x36 } },
{ { 0, 0x0a, 0x3e }, { 1, 0x00, 0x36 } },
{ { 0, 0x0a, 0x3f }, { 1, 0x00, 0x37 } },
{ { 0, 0x10, 0x33 }, { 1, 0x00, 0x37 } },
{ { 0, 0x0b, 0x3e }, { 1, 0x00, 0x38 } },
{ { 0, 0x0b, 0x3f }, { 1, 0x00, 0x38 } },
{ { 0, 0x0c, 0x3e }, { 1, 0x00, 0x39 } },
{ { 0, 0x10, 0x36 }, { 1, 0x00, 0x39 } },
{ { 0, 0x0c, 0x3f }, { 1, 0x00, 0x3a } },
{ { 0, 0x0d, 0x3e }, { 1, 0x00, 0x3a } },
{ { 0, 0x0d, 0x3f }, { 1, 0x00, 0x3b } },
{ { 0, 0x10, 0x39 }, { 1, 0x00, 0x3b } },
{ { 0, 0x0e, 0x3e }, { 1, 0x00, 0x3c } },
{ { 0, 0x0e, 0x3f }, { 1, 0x00, 0x3c } },
{ { 0, 0x0f, 0x3e }, { 1, 0x00, 0x3d } },
{ { 0, 0x10, 0x3c }, { 1, 0x00, 0x3d } },
{ { 0, 0x0f, 0x3f }, { 1, 0x00, 0x3e } },
{ { 0, 0x18, 0x2e }, { 1, 0x00, 0x3e } },
{ { 0, 0x10, 0x3e }, { 1, 0x00, 0x3f } },
{ { 0, 0x10, 0x3f }, { 1, 0x00, 0x3f } },
{ { 0, 0x11, 0x3e }, { 1, 0x01, 0x3f } },
{ { 0, 0x19, 0x2f }, { 1, 0x10, 0x30 } },
{ { 0, 0x11, 0x3f }, { 1, 0x02, 0x3f } },
{ { 0, 0x12, 0x3e }, { 1, 0x10, 0x31 } },
{ { 0, 0x12, 0x3f }, { 1, 0x03, 0x3f } },
{ { 0, 0x1b, 0x2e }, { 1, 0x10, 0x32 } },
{ { 0, 0x13, 0x3e }, { 1, 0x04, 0x3f } },
{ { 0, 0x13, 0x3f }, { 1, 0x10, 0x33 } },
{ { 0, 0x14, 0x3e }, { 1, 0x05, 0x3f } },
{ { 0, 0x1c, 0x2f }, { 1, 0x10, 0x34 } },
{ { 0, 0x14, 0x3f }, { 1, 0x06, 0x3f } },
{ { 0, 0x15, 0x3e }, { 1, 0x10, 0x35 } },
{ { 0, 0x15, 0x3f }, { 1, 0x07, 0x3f } },
{ { 0, 0x1e, 0x2e }, { 1, 0x10, 0x36 } },
{ { 0, 0x16, 0x3e }, { 1, 0x08, 0x3f } },
{ { 0, 0x16, 0x3f }, { 1, 0x10, 0x37 } },
{ { 0, 0x17, 0x3e }, { 1, 0x09, 0x3f } },
{ { 0, 0x1f, 0x2f }, { 1, 0x10, 0x38 } },
{ { 0, 0x17, 0x3f }, { 1, 0x0a, 0x3f } },
{ { 0, 0x18, 0x3e }, { 1, 0x10, 0x39 } },
{ { 0, 0x18, 0x3f }, { 1, 0x0b, 0x3f } },
{ { 0, 0x20, 0x2f }, { 1, 0x10, 0x3a } },
{ { 0, 0x19, 0x3e }, { 1, 0x0c, 0x3f } },
{ { 0, 0x19, 0x3f }, { 1, 0x10, 0x3b } },
{ { 0, 0x1a, 0x3e }, { 1, 0x0d, 0x3f } },
{ { 0, 0x20, 0x32 }, { 1, 0x10, 0x3c } },
{ { 0, 0x1a, 0x3f }, { 1, 0x0e, 0x3f } },
{ { 0, 0x1b, 0x3e }, { 1, 0x10, 0x3d } },
{ { 0, 0x1b, 0x3f }, { 1, 0x0f, 0x3f } },
{ { 0, 0x20, 0x35 }, { 1, 0x10, 0x3e } },
{ { 0, 0x1c, 0x3e }, { 1, 0x10, 0x3e } },
{ { 0, 0x1c, 0x3f }, { 1, 0x10, 0x3f } },
{ { 0, 0x1d, 0x3e }, { 1, 0x10, 0x3f } },
{ { 0, 0x20, 0x38 }, { 1, 0x11, 0x3f } },
{ { 0, 0x1d, 0x3f }, { 1, 0x11, 0x3f } },
{ { 0, 0x1e, 0x3e }, { 1, 0x12, 0x3f } },
{ { 0, 0x1e, 0x3f }, { 1, 0x12, 0x3f } },
{ { 0, 0x20, 0x3b }, { 1, 0x13, 0x3f } },
{ { 0, 0x1f, 0x3e }, { 1, 0x13, 0x3f } },
{ { 0, 0x1f, 0x3f }, { 1, 0x14, 0x3f } },
{ { 0, 0x20, 0x3d }, { 1, 0x14, 0x3f } },
{ { 0, 0x20, 0x3e }, { 1, 0x15, 0x3f } },
{ { 0, 0x20, 0x3f }, { 1, 0x15, 0x3f } },
{ { 0, 0x29, 0x2e }, { 1, 0x16, 0x3f } },
{ { 0, 0x21, 0x3e }, { 1, 0x16, 0x3f } },
{ { 0, 0x21, 0x3f }, { 1, 0x17, 0x3f } },
{ { 0, 0x22, 0x3e }, { 1, 0x17, 0x3f } },
{ { 0, 0x2a, 0x2f }, { 1, 0x18, 0x3f } },
{ { 0, 0x22, 0x3f }, { 1, 0x18, 0x3f } },
{ { 0, 0x23, 0x3e }, { 1, 0x19, 0x3f } },
{ { 0, 0x23, 0x3f }, { 1, 0x19, 0x3f } },
{ { 0, 0x2c, 0x2e }, { 1, 0x1a, 0x3f } },
{ { 0, 0x24, 0x3e }, { 1, 0x1a, 0x3f } },
{ { 0, 0x24, 0x3f }, { 1, 0x1b, 0x3f } },
{ { 0, 0x25, 0x3e }, { 1, 0x1b, 0x3f } },
{ { 0, 0x2d, 0x2f }, { 1, 0x1c, 0x3f } },
{ { 0, 0x25, 0x3f }, { 1, 0x1c, 0x3f } },
{ { 0, 0x26, 0x3e }, { 1, 0x1d, 0x3f } },
{ { 0, 0x26, 0x3f }, { 1, 0x1d, 0x3f } },
{ { 1, 0x1e, 0x3f }, { 0, 0x26, 0x3f } },
{ { 0, 0x27, 0x3e }, { 1, 0x1e, 0x3f } },
{ { 0, 0x27, 0x3f }, { 1, 0x1f, 0x3f } },
{ { 0, 0x28, 0x3e }, { 1, 0x1f, 0x3f } },
{ { 1, 0x20, 0x3f }, { 0, 0x28, 0x3e } },
{ { 0, 0x28, 0x3f }, { 1, 0x20, 0x3f } },
{ { 0, 0x29, 0x3e }, { 1, 0x21, 0x3f } },
{ { 0, 0x29, 0x3f }, { 1, 0x30, 0x30 } },
{ { 0, 0x30, 0x31 }, { 1, 0x22, 0x3f } },
{ { 0, 0x2a, 0x3e }, { 1, 0x30, 0x31 } },
{ { 0, 0x2a, 0x3f }, { 1, 0x23, 0x3f } },
{ { 0, 0x2b, 0x3e }, { 1, 0x30, 0x32 } },
{ { 0, 0x30, 0x34 }, { 1, 0x24, 0x3f } },
{ { 0, 0x2b, 0x3f }, { 1, 0x30, 0x33 } },
{ { 0, 0x2c, 0x3e }, { 1, 0x25, 0x3f } },
{ { 0, 0x2c, 0x3f }, { 1, 0x30, 0x34 } },
{ { 0, 0x30, 0x37 }, { 1, 0x26, 0x3f } },
{ { 0, 0x2d, 0x3e }, { 1, 0x30, 0x35 } },
{ { 0, 0x2d, 0x3f }, { 1, 0x27, 0x3f } },
{ { 0, 0x2e, 0x3e }, { 1, 0x30, 0x36 } },
{ { 0, 0x30, 0x3a }, { 1, 0x28, 0x3f } },
{ { 0, 0x2e, 0x3f }, { 1, 0x30, 0x37 } },
{ { 0, 0x2f, 0x3e }, { 1, 0x29, 0x3f } },
{ { 0, 0x2f, 0x3f }, { 1, 0x30, 0x38 } },
{ { 0, 0x30, 0x3d }, { 1, 0x2a, 0x3f } },
{ { 0, 0x30, 0x3e }, { 1, 0x30, 0x39 } },
{ { 1, 0x2b, 0x3f }, { 0, 0x30, 0x3e } },
{ { 0, 0x30, 0x3f }, { 1, 0x30, 0x3a } },
{ { 0, 0x31, 0x3e }, { 1, 0x2c, 0x3f } },
{ { 0, 0x31, 0x3f }, { 1, 0x30, 0x3b } },
{ { 1, 0x2d, 0x3f }, { 0, 0x31, 0x3f } },
{ { 0, 0x32, 0x3e }, { 1, 0x30, 0x3c } },
{ { 0, 0x32, 0x3f }, { 1, 0x2e, 0x3f } },
{ { 0, 0x33, 0x3e }, { 1, 0x30, 0x3d } },
{ { 1, 0x2f, 0x3f }, { 0, 0x33, 0x3e } },
{ { 0, 0x33, 0x3f }, { 1, 0x30, 0x3e } },
{ { 0, 0x34, 0x3e }, { 1, 0x30, 0x3e } },
{ { 0, 0x34, 0x3f }, { 1, 0x30, 0x3f } },
{ { 0, 0x34, 0x3f }, { 1, 0x30, 0x3f } },
{ { 0, 0x35, 0x3e }, { 1, 0x31, 0x3f } },
{ { 0, 0x35, 0x3f }, { 1, 0x31, 0x3f } },
{ { 0, 0x36, 0x3e }, { 1, 0x32, 0x3f } },
{ { 0, 0x36, 0x3e }, { 1, 0x32, 0x3f } },
{ { 0, 0x36, 0x3f }, { 1, 0x33, 0x3f } },
{ { 0, 0x37, 0x3e }, { 1, 0x33, 0x3f } },
{ { 0, 0x37, 0x3f }, { 1, 0x34, 0x3f } },
{ { 0, 0x37, 0x3f }, { 1, 0x34, 0x3f } },
{ { 0, 0x38, 0x3e }, { 1, 0x35, 0x3f } },
{ { 0, 0x38, 0x3f }, { 1, 0x35, 0x3f } },
{ { 0, 0x39, 0x3e }, { 1, 0x36, 0x3f } },
{ { 0, 0x39, 0x3e }, { 1, 0x36, 0x3f } },
{ { 0, 0x39, 0x3f }, { 1, 0x37, 0x3f } },
{ { 0, 0x3a, 0x3e }, { 1, 0x37, 0x3f } },
{ { 0, 0x3a, 0x3f }, { 1, 0x38, 0x3f } },
{ { 0, 0x3a, 0x3f }, { 1, 0x38, 0x3f } },
{ { 0, 0x3b, 0x3e }, { 1, 0x39, 0x3f } },
{ { 0, 0x3b, 0x3f }, { 1, 0x39, 0x3f } },
{ { 0, 0x3c, 0x3e }, { 1, 0x3a, 0x3f } },
{ { 0, 0x3c, 0x3e }, { 1, 0x3a, 0x3f } },
{ { 0, 0x3c, 0x3f }, { 1, 0x3b, 0x3f } },
{ { 0, 0x3d, 0x3e }, { 1, 0x3b, 0x3f } },
{ { 0, 0x3d, 0x3f }, { 1, 0x3c, 0x3f } },
{ { 0, 0x3d, 0x3f }, { 1, 0x3c, 0x3f } },
{ { 0, 0x3e, 0x3e }, { 1, 0x3d, 0x3f } },
{ { 0, 0x3e, 0x3f }, { 1, 0x3d, 0x3f } },
{ { 1, 0x3e, 0x3f }, { 0, 0x3e, 0x3f } },
{ { 0, 0x3f, 0x3f }, { 1, 0x3e, 0x3f } },
{ { 0, 0x3f, 0x3f }, { 1, 0x3f, 0x3f } }
};

View file

@ -1,172 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "FasTC/BPTCCompressor.h"
#include "CompressionMode.h"
#undef DBL_MAX
#include "FasTC/BitStream.h"
#include "FasTC/TexCompTypes.h"
#include <iostream>
#include <sstream>
#include <cstring>
#include "avpcl.h"
namespace BPTCC {
void GetBlock(uint32 x, uint32 y, uint32 width, const uint32 *pixels, Tile &t) {
for(uint32 j = 0; j < 4; j++)
for(uint32 i = 0; i < 4; i++) {
uint32 pixel = pixels[(y+j)*width + (x+i)];
t.data[j][i].X() = pixel & 0xFF;
t.data[j][i].Y() = (pixel >> 8) & 0xFF;
t.data[j][i].Z() = (pixel >> 16) & 0xFF;
t.data[j][i].W() = (pixel >> 24) & 0xFF;
}
}
class BlockLogger {
public:
BlockLogger(uint64 blockIdx, std::ostream &os)
: m_BlockIdx(blockIdx), m_Stream(os) { }
template<typename T>
friend std::ostream &operator<<(const BlockLogger &bl, const T &v);
uint64 m_BlockIdx;
std::ostream &m_Stream;
};
template<typename T>
std::ostream &operator<<(const BlockLogger &bl, const T &v) {
std::stringstream ss;
ss << bl.m_BlockIdx << ": " << v;
return bl.m_Stream << ss.str();
}
template<typename T>
static void PrintStat(const BlockLogger &lgr, const char *stat, const T &v) {
std::stringstream ss;
ss << stat << " -- " << v << std::endl;
lgr << ss.str();
}
// Compress an image using BC7 compression. Use the inBuf parameter to point
// to an image in 4-byte RGBA format. The width and height parameters specify
// the size of the image in pixels. The buffer pointed to by outBuf should be
// large enough to store the compressed image. This implementation has an 4:1
// compression ratio.
void CompressNVTT(const FasTC::CompressionJob &cj) {
const uint32 *inPixels = reinterpret_cast<const uint32 *>(cj.InBuf());
const uint32 kBlockSz = GetBlockSize(FasTC::eCompressionFormat_BPTC);
uint8 *outBuf = cj.OutBuf() + cj.CoordsToBlockIdx(cj.XStart(), cj.YStart()) * kBlockSz;
uint32 startX = cj.XStart();
const uint32 endY = std::min(cj.YEnd(), cj.Height() - 4);
for(uint32 j = cj.YStart(); j <= endY; j += 4) {
const uint32 endX = j == cj.YEnd()? cj.XEnd() : cj.Width();
for(uint32 i = startX; i < endX; i += 4) {
Tile block(4, 4);
GetBlock(i, j, cj.Width(), inPixels, block);
AVPCL::compress(block, reinterpret_cast<char *>(outBuf), NULL);
outBuf += kBlockSz;
}
startX = 0;
}
}
typedef double (*ModeCompressFunc)(const Tile &, char* out);
static ModeCompressFunc kModeFuncs[8] = {
AVPCL::compress_mode0,
AVPCL::compress_mode1,
AVPCL::compress_mode2,
AVPCL::compress_mode3,
AVPCL::compress_mode4,
AVPCL::compress_mode5,
AVPCL::compress_mode6,
AVPCL::compress_mode7
};
double CompressMode(uint32 mode, const Tile &t, char *out, BlockLogger &log) {
std::stringstream ss;
ss << "Mode_" << mode << "_error";
double mse = kModeFuncs[mode](t, out);
PrintStat(log, ss.str().c_str(), mse);
FasTC::BitStreamReadOnly strm(reinterpret_cast<uint8 *>(out));
while(!strm.ReadBit());
const CompressionMode::Attributes *attrs =
CompressionMode::GetAttributesForMode(mode);
const uint32 nSubsets = attrs->numSubsets;
ss.str("");
ss << "Mode_" << mode << "_shape";
uint32 shapeIdx = 0;
if ( nSubsets > 1 ) {
shapeIdx = strm.ReadBits(mode == 0? 4 : 6);
PrintStat(log, ss.str().c_str(), shapeIdx);
} else {
PrintStat(log, ss.str().c_str(), -1);
}
return mse;
}
void CompressNVTTWithStats(const FasTC::CompressionJob &cj, std::ostream *logStream) {
const uint32 *inPixels = reinterpret_cast<const uint32 *>(cj.InBuf());
const uint32 kBlockSz = GetBlockSize(FasTC::eCompressionFormat_BPTC);
uint8 *outBuf = cj.OutBuf() + cj.CoordsToBlockIdx(cj.XStart(), cj.YStart()) * kBlockSz;
uint32 startX = cj.XStart();
const uint32 endY = std::min(cj.YEnd(), cj.Height() - 4);
for(uint32 j = cj.YStart(); j <= endY; j += 4) {
const uint32 endX = j == cj.YEnd()? cj.XEnd() : cj.Width();
for(uint32 i = startX; i < endX; i += 4) {
Tile block(4, 4);
GetBlock(i, j, cj.Width(), inPixels, block);
if(logStream) {
BlockLogger logger(cj.CoordsToBlockIdx(i, j), *logStream);
char tempblock[16];
double msebest = 1e30;
for(uint32 mode = 0; mode < 8; mode++) {
double mse_mode = CompressMode(mode, block, tempblock, logger);
if(mse_mode < msebest) {
msebest = mse_mode;
memcpy(outBuf, tempblock, AVPCL::BLOCKSIZE);
}
}
} else {
AVPCL::compress(block, reinterpret_cast<char *>(outBuf), NULL);
}
outBuf += 16;
}
startX = 0;
}
}
} // namespace BC7C

View file

@ -1,312 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
// The original lisence from the code available at the following location:
// http://software.intel.com/en-us/vcsource/samples/fast-texture-compression
//
// This code has been modified significantly from the original.
//------------------------------------------------------------------------------
// Copyright 2011 Intel Corporation
// All Rights Reserved
//
// Permission is granted to use, copy, distribute and prepare derivative works
// of this software for any purpose and without fee, provided, that the above
// copyright notice and this statement appear in all copies. Intel makes no
// representations about the suitability of this software for any purpose. THIS
// SOFTWARE IS PROVIDED "AS IS." INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER
// INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR
// INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not assume
// any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
//
//------------------------------------------------------------------------------
#ifndef BPTCENCODER_SRC_BPTCCOMPRESSIONMODE_H_
#define BPTCENCODER_SRC_BPTCCOMPRESSIONMODE_H_
#include "RGBAEndpoints.h"
namespace FasTC {
class BitStream;
} // namespace FasTC
namespace BPTCC {
// Forward Declarations
struct VisitedState;
const int kMaxEndpoints = 3;
static const int kPBits[4][2] = {
{ 0, 0 },
{ 0, 1 },
{ 1, 0 },
{ 1, 1 }
};
class CompressionMode {
public:
static const uint32 kMaxNumSubsets = 3;
static const uint32 kNumModes = 8;
// This initializes the compression variables used in order to compress a list
// of clusters. We can increase the speed a tad by specifying whether or not
// the block is opaque or not.
explicit CompressionMode(int mode, const CompressionSettings &settings)
: m_IsOpaque(mode < 4)
, m_Attributes(&(kModeAttributes[mode]))
, m_SASteps(settings.m_NumSimulatedAnnealingSteps)
, m_ErrorMetric(settings.m_ErrorMetric)
, m_RotateMode(0)
, m_IndexMode(0)
{ }
~CompressionMode() { }
// These are all of the parameters required to define the data in a compressed
// BPTC block. The mode determines how these parameters will be translated
// into actual bits.
struct Params {
RGBAVector m_P1[kMaxNumSubsets], m_P2[kMaxNumSubsets];
uint8 m_Indices[kMaxNumSubsets][kMaxNumDataPoints];
uint8 m_AlphaIndices[kMaxNumDataPoints];
uint8 m_PbitCombo[kMaxNumSubsets];
int8 m_RotationMode;
int8 m_IndexMode;
uint16 m_ShapeIdx;
Params() { }
explicit Params(uint32 shape)
: m_RotationMode(-1), m_IndexMode(-1), m_ShapeIdx(shape) {
memset(m_Indices, 0xFF, sizeof(m_Indices));
memset(m_AlphaIndices, 0xFF, sizeof(m_AlphaIndices));
memset(m_PbitCombo, 0xFF, sizeof(m_PbitCombo));
}
};
// This outputs the parameters to the given bitstream based on the current
// compression mode. The first argument is not const because the mode and
// the value of the first index determines whether or not the indices need to
// be swapped. The final output bits will always be a valid BPTC block.
void Pack(Params &params, FasTC::BitStream &stream) const;
// This function compresses a group of clusters into the passed bitstream.
double Compress(Params &params, const int shapeIdx,
RGBACluster &cluster);
// This switch controls the quality of the simulated annealing optimizer. We
// will not make more than this many steps regardless of how bad the error is.
// Higher values will produce better quality results but will run slower.
// Default is 20.
static int MaxAnnealingIterations; // This is a setting
static const int kMaxAnnealingIterations = 256; // This is a limit
// P-bits are low-order bits that are shared across color channels. This enum
// says whether or not both endpoints share a p-bit or whether or not they
// even have a p-bit.
enum EPBitType {
ePBitType_Shared,
ePBitType_NotShared,
ePBitType_None
};
// These are all the per-mode attributes that can be set. They are specified
// in a table and we access them through the private m_Attributes variable.
static struct Attributes {
int modeNumber;
int numPartitionBits;
int numSubsets;
int numBitsPerIndex;
int numBitsPerAlpha;
int colorChannelPrecision;
int alphaChannelPrecision;
bool hasRotation;
bool hasIdxMode;
EPBitType pbitType;
} kModeAttributes[kNumModes];
// This returns the above attributes structure for the given mode.
static const Attributes *GetAttributesForMode(int mode) {
if(mode < 0 || mode >= 8) return NULL;
return &kModeAttributes[mode];
}
private:
const double m_IsOpaque;
const Attributes *const m_Attributes;
int m_SASteps;
ErrorMetric m_ErrorMetric;
int m_RotateMode;
int m_IndexMode;
void SetIndexMode(int mode) { m_IndexMode = mode; }
void SetRotationMode(int mode) { m_RotateMode = mode; }
int GetRotationMode() const {
return m_Attributes->hasRotation? m_RotateMode : 0;
}
int GetModeNumber() const { return m_Attributes->modeNumber; }
int GetNumberOfPartitionBits() const {
return m_Attributes->numPartitionBits;
}
int GetNumberOfSubsets() const { return m_Attributes->numSubsets; }
int GetNumberOfBitsPerIndex(int8 indexMode = -1) const {
if(indexMode < 0) indexMode = m_IndexMode;
if(indexMode == 0)
return m_Attributes->numBitsPerIndex;
else
return m_Attributes->numBitsPerAlpha;
}
int GetNumberOfBitsPerAlpha(int8 indexMode = -1) const {
if(indexMode < 0) indexMode = m_IndexMode;
if(indexMode == 0)
return m_Attributes->numBitsPerAlpha;
else
return m_Attributes->numBitsPerIndex;
}
// If we handle alpha separately, then we will consider the alpha channel
// to be not used whenever we do any calculations...
int GetAlphaChannelPrecision() const {
return m_Attributes->alphaChannelPrecision;
}
// This returns the proper error metric even if we have rotation bits set
RGBAVector GetErrorMetric() const {
const float *w = BPTCC::GetErrorMetric(m_ErrorMetric);
switch(GetRotationMode()) {
default:
case 0: return RGBAVector(w[0], w[1], w[2], w[3]);
case 1: return RGBAVector(w[3], w[1], w[2], w[0]);
case 2: return RGBAVector(w[0], w[3], w[2], w[1]);
case 3: return RGBAVector(w[0], w[1], w[3], w[2]);
}
}
EPBitType GetPBitType() const { return m_Attributes->pbitType; }
// This function creates an integer that represents the maximum values in each
// channel. We can use this to figure out the proper endpoint values for a
// given mode.
unsigned int GetQuantizationMask() const {
const int maskSeed = 0x80000000;
const uint32 alphaPrec = GetAlphaChannelPrecision();
const uint32 cbits = m_Attributes->colorChannelPrecision - 1;
const uint32 abits = GetAlphaChannelPrecision() - 1;
if(alphaPrec > 0) {
return (
(maskSeed >> (24 + cbits) & 0xFF) |
(maskSeed >> (16 + cbits) & 0xFF00) |
(maskSeed >> (8 + cbits) & 0xFF0000) |
(maskSeed >> abits & 0xFF000000)
);
} else {
return (
((maskSeed >> (24 + cbits) & 0xFF) |
(maskSeed >> (16 + cbits) & 0xFF00) |
(maskSeed >> (8 + cbits) & 0xFF0000)) &
(0x00FFFFFF)
);
}
}
int GetNumPbitCombos() const {
switch(GetPBitType()) {
case ePBitType_Shared: return 2;
case ePBitType_NotShared: return 4;
default:
case ePBitType_None: return 1;
}
}
const int *GetPBitCombo(int idx) const {
switch(GetPBitType()) {
case ePBitType_Shared: return (idx)? kPBits[3] : kPBits[0];
case ePBitType_NotShared: return kPBits[idx % 4];
default:
case ePBitType_None: return kPBits[0];
}
}
// This performs simulated annealing on the endpoints p1 and p2 based on the
// current MaxAnnealingIterations. This is set by calling the function
// SetQualityLevel
double OptimizeEndpointsForCluster(
const RGBACluster &cluster,
RGBAVector &p1, RGBAVector &p2,
uint8 *bestIndices,
uint8 &bestPbitCombo
) const;
// This function performs the heuristic to choose the "best" neighboring
// endpoints to p1 and p2 based on the compression mode (index precision,
// endpoint precision etc)
void PickBestNeighboringEndpoints(
const RGBACluster &cluster,
const RGBAVector &p1, const RGBAVector &p2,
const int curPbitCombo,
RGBAVector &np1, RGBAVector &np2,
int &nPbitCombo,
const VisitedState *visitedStates,
int nVisited,
float stepSz = 1.0f
) const;
// This is used by simulated annealing to determine whether or not the
// newError (from the neighboring endpoints) is sufficient to continue the
// annealing process from these new endpoints based on how good the oldError
// was, and how long we've been annealing (t)
bool AcceptNewEndpointError(double newError, double oldError, float t) const;
// This function figures out the best compression for the single color p, and
// places the endpoints in p1 and p2. If the compression mode supports p-bits,
// then we choose the best p-bit combo and return it as well.
double CompressSingleColor(const RGBAVector &p,
RGBAVector &p1, RGBAVector &p2,
uint8 &bestPbitCombo) const;
// Compress the cluster using a generalized cluster fit. This figures out the
// proper endpoints assuming that we have no alpha.
double CompressCluster(const RGBACluster &cluster,
RGBAVector &p1, RGBAVector &p2,
uint8 *bestIndices, uint8 &bestPbitCombo) const;
// Compress the non-opaque cluster using a generalized cluster fit, and place
// the endpoints within p1 and p2. The color indices and alpha indices are
// computed as well.
double CompressCluster(const RGBACluster &cluster,
RGBAVector &p1, RGBAVector &p2,
uint8 *bestIndices, uint8 *alphaIndices) const;
// This function takes two endpoints in the continuous domain (as floats) and
// clamps them to the nearest grid points based on the compression mode (and
// possible pbit values)
void ClampEndpointsToGrid(RGBAVector &p1, RGBAVector &p2,
uint8 &bestPBitCombo) const;
};
extern const uint32 kInterpolationValues[4][16][2];
} // namespace BPTCC {
#endif // BPTCENCODER_SRC_BPTCCOMPRESSIONMODE_H_

View file

@ -1,205 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
// The original lisence from the code available at the following location:
// http://software.intel.com/en-us/vcsource/samples/fast-texture-compression
//
// This code has been modified significantly from the original.
//------------------------------------------------------------------------------
// Copyright 2011 Intel Corporation
// All Rights Reserved
//
// Permission is granted to use, copy, distribute and prepare derivative works
// of this software for any purpose and without fee, provided, that the above
// copyright notice and this statement appear in all copies. Intel makes no
// representations about the suitability of this software for any purpose. THIS
// SOFTWARE IS PROVIDED "AS IS." INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER
// INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR
// INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not assume
// any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
//
//------------------------------------------------------------------------------
#ifndef BPTCENCODER_SRC_BC7COMPRESSIONMODESIMD_H_
#define BPTCENCODER_SRC_BC7COMPRESSIONMODESIMD_H_
#include "TexCompTypes.h"
#include "RGBAEndpointsSIMD.h"
// Forward Declarations
class BitStream;
static const int kPBits[4][2] = {
{ 0, 0 },
{ 0, 1 },
{ 1, 0 },
{ 1, 1 }
};
class BC7CompressionModeSIMD {
public:
static const int kMaxNumSubsets = 3;
static const int kNumModes = 8;
enum EPBitType {
ePBitType_Shared,
ePBitType_NotShared,
ePBitType_None
};
BC7CompressionModeSIMD(int mode, double err)
: m_EstimatedError(err)
, m_Attributes(&(kModeAttributes[mode]))
{ }
~BC7CompressionModeSIMD() { }
static int NumUses[8];
static void ResetNumUses() { memset(NumUses, 0, sizeof(NumUses)); }
double Compress(BitStream &stream, const int shapeIdx,
const RGBAClusterSIMD *clusters) const;
// This switch controls the quality of the simulated annealing optimizer. We
// will not make more than this many steps regardless of how bad the error is.
// Higher values will produce better quality results but will run slower.
// Default is 50.
static int MaxAnnealingIterations; // This is a setting
private:
static struct Attributes {
int modeNumber;
int numPartitionBits;
int numSubsets;
int numBitsPerIndex;
int redChannelPrecision;
int greenChannelPrecision;
int blueChannelPrecision;
int alphaChannelPrecision;
EPBitType pbitType;
} kModeAttributes[kNumModes];
protected:
const Attributes *const m_Attributes;
int GetModeNumber() const { return m_Attributes->modeNumber; }
int GetNumberOfPartitionBits() const {
return m_Attributes->numPartitionBits;
}
int GetNumberOfSubsets() const { return m_Attributes->numSubsets; }
int GetNumberOfBitsPerIndex() const { return m_Attributes->numBitsPerIndex; }
int GetRedChannelPrecision() const {
return m_Attributes->redChannelPrecision;
}
int GetGreenChannelPrecision() const {
return m_Attributes->greenChannelPrecision;
}
int GetBlueChannelPrecision() const {
return m_Attributes->blueChannelPrecision;
}
int GetAlphaChannelPrecision() const {
return m_Attributes->alphaChannelPrecision;
}
EPBitType GetPBitType() const { return m_Attributes->pbitType; }
// !SPEED! Add this to the attributes lookup table
void GetQuantizationMask(__m128i &mask) const {
const int maskSeed = 0x80000000;
const uint32 abits = 24 + GetAlphaChannelPrecision() - 1;
const uint32 rbits = 24 + GetRedChannelPrecision() - 1;
const uint32 gbits = 24 + GetGreenChannelPrecision() - 1;
const uint32 bbits = 24 + GetBlueChannelPrecision() - 1;
mask = _mm_set_epi32(
(GetAlphaChannelPrecision() > 0)? (maskSeed >> abits & 0xFF) : 0xFF,
(maskSeed >> rbits & 0xFF),
(maskSeed >> gbits & 0xFF),
(maskSeed >> bbits & 0xFF)
);
}
int GetNumPbitCombos() const {
switch(GetPBitType()) {
case ePBitType_Shared: return 2;
case ePBitType_NotShared: return 4;
default:
case ePBitType_None: return 1;
}
}
const int *GetPBitCombo(int idx) const {
switch(GetPBitType()) {
case ePBitType_Shared: return (idx)? kPBits[3] : kPBits[0];
case ePBitType_NotShared: return kPBits[idx % 4];
default:
case ePBitType_None: return kPBits[0];
}
}
double OptimizeEndpointsForCluster(const RGBAClusterSIMD &cluster,
RGBAVectorSIMD &p1, RGBAVectorSIMD &p2,
__m128i *bestIndices,
int &bestPbitCombo) const;
struct VisitedState {
RGBAVectorSIMD p1;
RGBAVectorSIMD p2;
int pBitCombo;
};
void PickBestNeighboringEndpoints(
const RGBAClusterSIMD &cluster,
const RGBAVectorSIMD &p1, const RGBAVectorSIMD &p2,
const int curPbitCombo,
RGBAVectorSIMD &np1, RGBAVectorSIMD &np2,
int &nPbitCombo,
const __m128 &stepVec
) const;
bool AcceptNewEndpointError(float newError, float oldError, float temp) const;
double CompressSingleColor(const RGBAVectorSIMD &p,
RGBAVectorSIMD &p1, RGBAVectorSIMD &p2,
int &bestPbitCombo) const;
double CompressCluster(const RGBAClusterSIMD &cluster,
RGBAVectorSIMD &p1, RGBAVectorSIMD &p2,
__m128i *bestIndices,
int &bestPbitCombo) const;
void ClampEndpointsToGrid(RGBAVectorSIMD &p1, RGBAVectorSIMD &p2,
int &bestPBitCombo) const;
int GetSubsetForIndex(int idx, const int shapeIdx) const;
int GetAnchorIndexForSubset(int subset, const int shapeIdx) const;
double GetEstimatedError() const { return m_EstimatedError; }
const double m_EstimatedError;
};
extern const __m128i kBC7InterpolationValuesSIMD[4][16][2];
extern const uint32 kBC7InterpolationValuesScalar[4][16][2];
#endif // BPTCENCODER_SRC_BC7COMPRESSIONMODESIMD_H_

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,369 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "FasTC/BPTCCompressor.h"
#include "FasTC/Shapes.h"
#include "FasTC/TexCompTypes.h"
#include "FasTC/BitStream.h"
using FasTC::BitStream;
using FasTC::BitStreamReadOnly;
#include "AnchorTables.h"
#include "CompressionMode.h"
using BPTCC::CompressionMode;
static int UnpackParams(const uint8 block[16], CompressionMode::Params &params) {
BitStreamReadOnly strm(block);
uint32 mode = 0;
while(!strm.ReadBit()) {
mode++;
}
const CompressionMode::Attributes *attrs =
CompressionMode::GetAttributesForMode(mode);
const uint32 nSubsets = attrs->numSubsets;
params.m_IndexMode = 0;
params.m_RotationMode = 0;
params.m_ShapeIdx = 0;
if ( nSubsets > 1 ) {
params.m_ShapeIdx = strm.ReadBits(mode == 0? 4 : 6);
} else if( attrs->hasRotation ) {
params.m_RotationMode = strm.ReadBits(2);
if( attrs->hasIdxMode ) {
params.m_IndexMode = strm.ReadBit();
}
}
assert(params.m_IndexMode < 2);
assert(params.m_RotationMode < 4);
assert(params.m_ShapeIdx < ((mode == 0)? 16U : 64U));
uint32 cp = attrs->colorChannelPrecision;
const uint32 shift = 8 - cp;
uint8 eps[3][2][4];
for(uint32 ch = 0; ch < 3; ch++)
for(uint32 i = 0; i < nSubsets; i++)
for(uint32 ep = 0; ep < 2; ep++)
eps[i][ep][ch] = strm.ReadBits(cp) << shift;
uint32 ap = attrs->alphaChannelPrecision;
const uint32 ash = 8 - ap;
if(ap == 0) {
for(uint32 i = 0; i < nSubsets; i++)
for(uint32 ep = 0; ep < 2; ep++)
eps[i][ep][3] = 0xFF;
} else {
for(uint32 i = 0; i < nSubsets; i++)
for(uint32 ep = 0; ep < 2; ep++)
eps[i][ep][3] = strm.ReadBits(ap) << ash;
}
// Handle pbits
switch(attrs->pbitType) {
case CompressionMode::ePBitType_None:
// Do nothing.
break;
case CompressionMode::ePBitType_Shared:
cp += 1;
ap += 1;
for(uint32 i = 0; i < nSubsets; i++) {
uint32 pbit = strm.ReadBit();
for(uint32 j = 0; j < 2; j++)
for(uint32 ch = 0; ch < kNumColorChannels; ch++) {
const uint32 prec = ch == 3? ap : cp;
eps[i][j][ch] |= pbit << (8-prec);
}
}
break;
case CompressionMode::ePBitType_NotShared:
cp += 1;
ap += 1;
for(uint32 i = 0; i < nSubsets; i++)
for(uint32 j = 0; j < 2; j++) {
uint32 pbit = strm.ReadBit();
for(uint32 ch = 0; ch < kNumColorChannels; ch++) {
const uint32 prec = ch == 3? ap : cp;
eps[i][j][ch] |= pbit << (8-prec);
}
}
break;
}
// Quantize endpoints...
for(uint32 i = 0; i < nSubsets; i++)
for(uint32 j = 0; j < 2; j++)
for(uint32 ch = 0; ch < kNumColorChannels; ch++) {
const uint32 prec = ch == 3? ap : cp;
eps[i][j][ch] |= eps[i][j][ch] >> prec;
}
for(uint32 i = 0; i < nSubsets; i++) {
params.m_P1[i] = RGBAVector(eps[i][0][0], eps[i][0][1], eps[i][0][2], eps[i][0][3]);
params.m_P2[i] = RGBAVector(eps[i][1][0], eps[i][1][1], eps[i][1][2], eps[i][1][3]);
}
// Figure out indices...
uint32 alphaIndices[kMaxNumDataPoints];
uint32 colorIndices[kMaxNumDataPoints];
int nBitsPerAlpha = attrs->numBitsPerAlpha;
int nBitsPerColor = attrs->numBitsPerIndex;
uint32 idxPrec = attrs->numBitsPerIndex;
for(uint32 i = 0; i < kMaxNumDataPoints; i++) {
uint32 subset = BPTCC::GetSubsetForIndex(i, params.m_ShapeIdx, nSubsets);
int idx = 0;
if(BPTCC::GetAnchorIndexForSubset(subset, params.m_ShapeIdx, nSubsets) == i) {
idx = strm.ReadBits(idxPrec - 1);
} else {
idx = strm.ReadBits(idxPrec);
}
colorIndices[i] = idx;
}
idxPrec = attrs->numBitsPerAlpha;
if(idxPrec == 0) {
memcpy(alphaIndices, colorIndices, sizeof(alphaIndices));
} else {
for(uint32 i = 0; i < kMaxNumDataPoints; i++) {
uint32 subset = BPTCC::GetSubsetForIndex(i, params.m_ShapeIdx, nSubsets);
int idx = 0;
if(BPTCC::GetAnchorIndexForSubset(subset, params.m_ShapeIdx, nSubsets) == i) {
idx = strm.ReadBits(idxPrec - 1);
} else {
idx = strm.ReadBits(idxPrec);
}
alphaIndices[i] = idx;
}
if(params.m_IndexMode) {
for(uint32 i = 0; i < kMaxNumDataPoints; i++) {
std::swap(alphaIndices[i], colorIndices[i]);
}
std::swap(nBitsPerAlpha, nBitsPerColor);
}
}
for (uint32 i = 0; i < kMaxNumDataPoints; ++i) {
params.m_Indices[0][i] = static_cast<uint8>(colorIndices[i]);
params.m_AlphaIndices[i] = static_cast<uint8>(alphaIndices[i]);
}
assert(strm.GetBitsRead() == 128);
return mode;
}
static FasTC::Pixel ConvertEndpoint(const int mode, const RGBAVector &ep) {
const CompressionMode::Attributes *attrs =
BPTCC::CompressionMode::GetAttributesForMode(mode);
uint8 depth[4];
memset(depth, 0, sizeof(depth));
depth[0] = attrs->colorChannelPrecision;
depth[1] = attrs->colorChannelPrecision;
depth[2] = attrs->colorChannelPrecision;
depth[3] = attrs->alphaChannelPrecision;
if (attrs->pbitType != CompressionMode::ePBitType_None) {
for (int i = 0; i < 4; i++) {
if (depth[i] != 0) {
depth[i] += 1;
}
}
}
for (int i = 0; i < 4; i++) {
assert(depth[i] <= 8);
}
FasTC::Pixel p;
p.ChangeBitDepth(depth);
p.R() = static_cast<int16>(ep.R()) >> (8 - depth[0]);
p.G() = static_cast<int16>(ep.G()) >> (8 - depth[1]);
p.B() = static_cast<int16>(ep.B()) >> (8 - depth[2]);
if (depth[3] == 0) {
p.A() = 0xFF;
} else {
p.A() = static_cast<int16>(ep.A()) >> (8 - depth[3]);
}
return p;
}
static void DecompressBC7Block(const uint8 block[16], BPTCC::LogicalBlock *out) {
CompressionMode::Params params;
int mode = UnpackParams(block, params);
const CompressionMode::Attributes *attrs =
BPTCC::CompressionMode::GetAttributesForMode(mode);
BPTCC::Shape shape;
shape.m_NumPartitions = attrs->numSubsets;
shape.m_Index = params.m_ShapeIdx;
out->m_Mode = static_cast<BPTCC::EBlockMode>(1 << mode);
out->m_Shape = shape;
for (int i = 0; i < attrs->numSubsets; ++i) {
out->m_Endpoints[i][0] = ConvertEndpoint(mode, params.m_P1[i]);
out->m_Endpoints[i][1] = ConvertEndpoint(mode, params.m_P2[i]);
}
for (uint32 i = 0; i < kMaxNumDataPoints; ++i) {
out->m_Indices[i] = static_cast<uint32>(params.m_Indices[0][i]);
out->m_AlphaIndices[i] = static_cast<uint32>(params.m_AlphaIndices[i]);
}
}
static void DecompressBC7Block(const uint8 block[16], uint32 outBuf[16]) {
CompressionMode::Params params;
int mode = UnpackParams(block, params);
const CompressionMode::Attributes *attrs =
BPTCC::CompressionMode::GetAttributesForMode(mode);
const int nBitsPerAlpha = attrs->numBitsPerAlpha;
const int nBitsPerColor = attrs->numBitsPerIndex;
// Get final colors by interpolating...
for(uint32 i = 0; i < kMaxNumDataPoints; i++) {
const uint32 subset = BPTCC::GetSubsetForIndex(i, params.m_ShapeIdx, attrs->numSubsets);
uint32 &pixel = outBuf[i];
pixel = 0;
for(int ch = 0; ch < 4; ch++) {
if(ch == 3 && nBitsPerAlpha > 0) {
uint32 i0 =
BPTCC::kInterpolationValues[nBitsPerAlpha - 1][params.m_AlphaIndices[i]][0];
uint32 i1 =
BPTCC::kInterpolationValues[nBitsPerAlpha - 1][params.m_AlphaIndices[i]][1];
const uint32 ep1 = static_cast<uint32>(params.m_P1[subset].A());
const uint32 ep2 = static_cast<uint32>(params.m_P2[subset].A());
const uint8 ip = (((ep1 * i0 + ep2 * i1) + 32) >> 6) & 0xFF;
pixel |= ip << 24;
} else {
uint32 i0 =
BPTCC::kInterpolationValues[nBitsPerColor - 1][params.m_Indices[0][i]][0];
uint32 i1 =
BPTCC::kInterpolationValues[nBitsPerColor - 1][params.m_Indices[0][i]][1];
const uint32 ep1 = static_cast<uint32>(params.m_P1[subset][ch]);
const uint32 ep2 = static_cast<uint32>(params.m_P2[subset][ch]);
const uint8 ip = (((ep1 * i0 + ep2 * i1) + 32) >> 6) & 0xFF;
pixel |= ip << (8*ch);
}
}
// Swap colors if necessary...
uint8 *pb = reinterpret_cast<uint8 *>(&pixel);
switch(params.m_RotationMode) {
default:
case 0:
// Do nothing
break;
case 1:
std::swap(pb[0], pb[3]);
break;
case 2:
std::swap(pb[1], pb[3]);
break;
case 3:
std::swap(pb[2], pb[3]);
break;
}
}
}
namespace BPTCC {
// Convert the image from a BC7 buffer to a RGBA8 buffer
void DecompressLogical(const FasTC::DecompressionJob &dj,
std::vector<LogicalBlock> *out) {
if (!out) { return; }
out->clear();
out->resize(dj.Height() * dj.Width() / 16);
const uint8 *inBuf = dj.InBuf();
int blockIdx = 0;
for(unsigned int j = 0; j < dj.Height(); j += 4) {
for(unsigned int i = 0; i < dj.Width(); i += 4) {
DecompressBC7Block(inBuf, &(out->at(blockIdx++)));
inBuf += 16;
}
}
}
// Convert the image from a BC7 buffer to a RGBA8 buffer
void Decompress(const FasTC::DecompressionJob &dj) {
const uint8 *inBuf = dj.InBuf();
uint32 *outBuf = reinterpret_cast<uint32 *>(dj.OutBuf());
for(unsigned int j = 0; j < dj.Height(); j += 4) {
for(unsigned int i = 0; i < dj.Width(); i += 4) {
uint32 pixels[16];
DecompressBC7Block(inBuf, pixels);
uint32 decompWidth = std::min(4U, dj.Width() - i);
uint32 decompHeight = std::min(4U, dj.Height() - j);
uint32 *outRow = outBuf + j * dj.Width() + i;
for (uint32 jj = 0; jj < decompHeight; ++jj) {
memcpy(outRow + jj*dj.Width(), pixels + 4 * jj, decompWidth * sizeof(pixels[0]));
}
inBuf += 16;
}
}
}
} // namespace BPTCC

View file

@ -1,134 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "ParallelStage.h"
#include <assert.h>
#include <string.h>
/*
const BPTCParallelStage stage;
// This is the stream of data that will be used to read the block data.
const unsigned char *const m_InBuf;
// This is the destination buffer to which the block data will be written to.
unsigned char *const m_OutBuf;
// This is the array of block offsets that belong to this stage.
uint32 *m_Blocks;
// This is the total number of blocks in the given image.
const uint32 m_TotalNumBlocks;
// This is the total number of blocks in this particular stage.
uint32 m_NumBlocks;
*/
ParallelStage::ParallelStage(
BPTCParallelStage stage,
const unsigned char *inbuf,
unsigned char *outbuf,
uint32 numBlocks,
uint32 outBlockSz,
uint32 inBlockSz
)
: m_Stage(stage)
, m_InBuf(inbuf)
, m_OutBuf(outbuf)
, m_Blocks(new uint32[numBlocks])
, m_TotalNumBlocks(numBlocks)
, m_NumBlocks(0)
, m_OutBlockSz(outBlockSz)
, m_InBlockSz(inBlockSz)
{
assert(numBlocks > 0);
}
ParallelStage::ParallelStage(const ParallelStage &other)
: m_Stage(other.m_Stage)
, m_InBuf(other.m_InBuf)
, m_OutBuf(other.m_OutBuf)
, m_Blocks(new uint32[other.m_NumBlocks])
, m_TotalNumBlocks(other.m_TotalNumBlocks)
, m_NumBlocks(other.m_NumBlocks)
, m_OutBlockSz(other.m_OutBlockSz)
, m_InBlockSz(other.m_InBlockSz)
{
memcpy(m_Blocks, other.m_Blocks, m_NumBlocks * sizeof(m_Blocks[0]));
}
ParallelStage &ParallelStage::operator=(const ParallelStage &other) {
assert(m_Stage == other.m_Stage);
assert(m_InBuf == other.m_InBuf);
assert(m_OutBuf == other.m_OutBuf);
assert(m_TotalNumBlocks == other.m_TotalNumBlocks);
assert(m_NumBlocks == other.m_NumBlocks);
assert(m_OutBlockSz == other.m_OutBlockSz);
assert(m_InBlockSz == other.m_InBlockSz);
memcpy(m_Blocks, other.m_Blocks, m_NumBlocks * sizeof(m_Blocks[0]));
return *this;
}
ParallelStage::~ParallelStage() {
if(m_Blocks) {
delete [] m_Blocks;
m_Blocks = 0;
}
}
void ParallelStage::AddBlock(uint32 blockNum) {
assert(m_NumBlocks < m_TotalNumBlocks);
m_Blocks[m_NumBlocks++] = blockNum;
}
uint32 ParallelStage::LoadBlocks(uint32 blockOffset, uint32 numBlocks, unsigned char *dst) {
if(!dst)
return 0;
if(blockOffset + numBlocks > m_NumBlocks)
return 0;
int lastBlock = blockOffset + numBlocks;
for(int i = blockOffset; i < lastBlock; i++)
{
uint32 block = m_Blocks[i];
uint32 bOffset = block * m_InBlockSz;
memcpy(dst + ((i - blockOffset) * m_InBlockSz), m_InBuf + bOffset, m_InBlockSz);
}
return 0;
}
bool ParallelStage::WriteBlocks(uint32 blockOffset, uint32 numBlocks, const unsigned char *src) {
if(!src)
return false;
if(blockOffset + numBlocks > m_NumBlocks)
return false;
int lastBlock = blockOffset + numBlocks;
for(int i = blockOffset; i < lastBlock; i++) {
uint32 block = m_Blocks[i];
uint32 bOffset = block * m_OutBlockSz;
memcpy(m_OutBuf + bOffset, src + ((i-blockOffset) * m_OutBlockSz), m_OutBlockSz);
}
return true;
}

View file

@ -1,75 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "FasTC/TexCompTypes.h"
enum BPTCParallelStage {
eParallelStage_Uniform,
eParallelStage_Partitioned,
eParallelStage_Normal,
kNumParallelStages
};
class ParallelStage {
public:
ParallelStage(
BPTCParallelStage stage,
const unsigned char *inbuf,
unsigned char *outbuf,
uint32 numBlocks,
uint32 outBlockSz = 16,
uint32 inBlockSz = 64
);
ParallelStage(const ParallelStage &);
ParallelStage &operator=(const ParallelStage &);
~ParallelStage();
const BPTCParallelStage m_Stage;
// Adds the block number to the list of blocks for this parallel stage
void AddBlock(uint32 blockNum);
// Loads the desired number of blocks into the destination buffer. Returns
// the number of blocks loaded.
uint32 LoadBlocks(uint32 blockOffset, uint32 numBlocks, unsigned char *dst);
// Writes the block data from src into numBlocks blocks starting from
// the block given by blockOffset.
bool WriteBlocks(uint32 blockOffset, uint32 numBlocks, const unsigned char *src);
private:
// This is the stream of data that will be used to read the block data.
const unsigned char *const m_InBuf;
// This is the destination buffer to which the block data will be written to.
unsigned char *const m_OutBuf;
// This is the array of block offsets that belong to this stage.
uint32 *m_Blocks;
// This is the total number of blocks in the given image.
const uint32 m_TotalNumBlocks;
// This is the total number of blocks in this particular stage.
uint32 m_NumBlocks;
const uint32 m_OutBlockSz;
const uint32 m_InBlockSz;
};

View file

@ -1,441 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
// The original lisence from the code available at the following location:
// http://software.intel.com/en-us/vcsource/samples/fast-texture-compression
//
// This code has been modified significantly from the original.
//------------------------------------------------------------------------------
// Copyright 2011 Intel Corporation
// All Rights Reserved
//
// Permission is granted to use, copy, distribute and prepare derivative works
// of this software for any purpose and without fee, provided, that the above
// copyright notice and this statement appear in all copies. Intel makes no
// representations about the suitability of this software for any purpose. THIS
// SOFTWARE IS PROVIDED "AS IS." INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER
// INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR
// INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not assume
// any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
//
//------------------------------------------------------------------------------
#include "FasTC/BPTCConfig.h"
#include "FasTC/BPTCCompressor.h"
#include "RGBAEndpoints.h"
#include "CompressionMode.h"
#include <cassert>
#include <cfloat>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#ifndef min
template <typename T>
static T min(const T &a, const T &b) {
return (a > b)? b : a;
}
#endif
#ifndef max
template <typename T>
static T max(const T &a, const T &b) {
return (a > b)? a : b;
}
#endif
///////////////////////////////////////////////////////////////////////////////
//
// Static helper functions
//
///////////////////////////////////////////////////////////////////////////////
static inline uint32 CountBitsInMask(uint8 n) {
#if defined(_WIN64) || defined(__x86_64__) || defined(NO_INLINE_ASSEMBLY)
if(!n) return 0; // no bits set
if(!(n & (n-1))) return 1; // power of two
uint32 c;
for(c = 0; n; c++) {
n &= n - 1;
}
return c;
#else
#ifdef _MSC_VER
__asm {
mov eax, 8
movzx ecx, n
bsf ecx, ecx
sub eax, ecx
}
#else
uint32 ans;
__asm__("movl $8, %%eax;"
"movzbl %b1, %%ecx;"
"bsf %%ecx, %%ecx;"
"subl %%ecx, %%eax;"
"movl %%eax, %0;"
: "=Q"(ans)
: "b"(n)
: "%eax", "%ecx"
);
return ans;
#endif
#endif
}
template <typename ty>
static inline void clamp(ty &x, const ty &min, const ty &max) {
x = (x < min)? min : ((x > max)? max : x);
}
// absolute distance. It turns out the compiler does a much
// better job of optimizing this than we can, since we can't
// translate the values to/from registers
template <typename ty>
static ty sad(ty a, ty b) {
return (a > b)? a - b : b - a;
}
///////////////////////////////////////////////////////////////////////////////
//
// RGBAVector implementation
//
///////////////////////////////////////////////////////////////////////////////
uint8 QuantizeChannel(const uint8 val, const uint8 mask, const int pBit) {
// If the mask is all the bits, then we can just return the value.
if(mask == 0xFF) {
return val;
}
// Otherwise if the mask is no bits then we'll assume that they want
// all the bits ... this is only really relevant for alpha...
if(mask == 0x0) {
return 0xFF;
}
uint32 prec = CountBitsInMask(mask);
const uint32 step = 1 << (8 - prec);
assert(step-1 == uint8(~mask));
uint32 lval = val & mask;
uint32 hval = lval + step;
if(pBit >= 0) {
prec++;
lval |= !!(pBit) << (8 - prec);
hval |= !!(pBit) << (8 - prec);
}
if(lval > val) {
lval -= step;
hval -= step;
}
lval |= lval >> prec;
hval |= hval >> prec;
if(sad<uint8>(val, lval) < sad<uint8>(val, hval))
return lval;
else
return hval;
}
uint32 RGBAVector::ToPixel(const uint32 channelMask, const int pBit) const {
const uint8 pRet0 = QuantizeChannel(uint32(R() + 0.5) & 0xFF, channelMask & 0xFF, pBit);
const uint8 pRet1 = QuantizeChannel(uint32(G() + 0.5) & 0xFF, (channelMask >> 8) & 0xFF, pBit);
const uint8 pRet2 = QuantizeChannel(uint32(B() + 0.5) & 0xFF, (channelMask >> 16) & 0xFF, pBit);
const uint8 pRet3 = QuantizeChannel(uint32(A() + 0.5) & 0xFF, (channelMask >> 24) & 0xFF, pBit);
const uint32 ret = pRet0 | (pRet1 << 8) | (pRet2 << 16) | (pRet3 << 24);
return ret;
}
///////////////////////////////////////////////////////////////////////////////
//
// Cluster implementation
//
///////////////////////////////////////////////////////////////////////////////
template<typename T>
static inline T Clamp(const T &x, const T &a, const T &b) {
return std::max(a, std::min(x, b));
}
template<const uint8 nBuckets>
double RGBACluster::QuantizedError(
const RGBAVector &p1, const RGBAVector &p2,
uint32 bitMask, const RGBAVector &errorMetricVec,
const int pbits[2], uint8 *indices
) const {
// nBuckets should be a power of two.
const uint8 indexPrec = static_cast<uint8>(log(static_cast<float>(nBuckets))/log(2.0f));
assert(!(nBuckets & (nBuckets - 1)));
assert(indexPrec >= 2 && indexPrec <= 4);
typedef uint32 tInterpPair[2];
typedef tInterpPair tInterpLevel[16];
const tInterpLevel *interpVals = BPTCC::kInterpolationValues + (indexPrec - 1);
uint32 qp1, qp2;
if(pbits) {
qp1 = p1.ToPixel(bitMask, pbits[0]);
qp2 = p2.ToPixel(bitMask, pbits[1]);
} else {
qp1 = p1.ToPixel(bitMask);
qp2 = p2.ToPixel(bitMask);
}
const RGBAVector uqp1 = RGBAVector(0, qp1);
const RGBAVector uqp2 = RGBAVector(0, qp2);
const float uqplsq = (uqp1 - uqp2).LengthSq();
const RGBAVector uqpdir = uqp2 - uqp1;
const uint8 *pqp1 = reinterpret_cast<const uint8 *>(&qp1);
const uint8 *pqp2 = reinterpret_cast<const uint8 *>(&qp2);
const RGBAVector metric = errorMetricVec;
float totalError = 0.0;
if(uqplsq == 0) {
// If both endpoints are the same then the indices don't matter...
for(uint32 i = 0; i < GetNumPoints(); i++) {
const uint32 pixel = GetPixel(i);
const uint8 *pb = (const uint8 *)(&pixel);
uint32 interp0 = (*interpVals)[0][0];
uint32 interp1 = (*interpVals)[0][1];
RGBAVector errorVec (0.0f);
for(uint32 k = 0; k < 4; k++) {
const uint32 ip = (((pqp1[k] * interp0) + (pqp2[k] * interp1) + 32) >> 6) & 0xFF;
const uint8 dist = sad<uint8>(pb[k], ip);
errorVec[k] = static_cast<float>(dist) * metric[k];
}
totalError += errorVec * errorVec;
if(indices)
indices[i] = 0;
}
return totalError;
}
for(uint32 i = 0; i < GetNumPoints(); i++) {
// Project this point unto the direction denoted by uqpdir...
const RGBAVector pt = GetPoint(i);
#if 0
const float pct = Clamp(((pt - uqp1) * uqpdir) / uqplsq, 0.0f, 1.0f);
const int32 j1 = static_cast<int32>(pct * static_cast<float>(nBuckets-1));
const int32 j2 = static_cast<int32>(pct * static_cast<float>(nBuckets-1) + 0.7);
#else
const float pct = ((pt - uqp1) * uqpdir) / uqplsq;
int32 j1 = static_cast<int32>(floor(pct * static_cast<float>(nBuckets-1)));
int32 j2 = static_cast<int32>(ceil(pct * static_cast<float>(nBuckets-1)));
j1 = std::min(std::max(0, j1), nBuckets - 1);
j2 = std::min(j2, nBuckets - 1);
#endif
assert(j1 >= 0 && j2 <= nBuckets - 1);
const uint32 pixel = GetPixel(i);
const uint8 *pb = (const uint8 *)(&pixel);
float minError = FLT_MAX;
uint8 bestBucket = 0;
int32 j = j1;
do {
uint32 interp0 = (*interpVals)[j][0];
uint32 interp1 = (*interpVals)[j][1];
RGBAVector errorVec (0.0f);
for(uint32 k = 0; k < 4; k++) {
const uint32 ip = (((pqp1[k] * interp0) + (pqp2[k] * interp1) + 32) >> 6) & 0xFF;
const uint8 dist = sad<uint8>(pb[k], ip);
errorVec[k] = static_cast<float>(dist) * metric[k];
}
float error = errorVec * errorVec;
if(error < minError) {
minError = error;
bestBucket = j;
}
// Conceptually, once the error starts growing, it doesn't stop growing (we're moving
// farther away from the reference point along the line). Hence we can early out here.
// However, quanitzation artifacts mean that this is not ALWAYS the case, so we do suffer
// about 0.01 RMS error.
else if(error > minError) {
break;
}
} while(++j <= j2);
totalError += minError;
if(indices) indices[i] = bestBucket;
}
return totalError;
}
template double RGBACluster::QuantizedError<4>(
const RGBAVector &p1, const RGBAVector &p2,
uint32 bitMask, const RGBAVector &errorMetricVec,
const int pbits[2], uint8 *indices) const;
template double RGBACluster::QuantizedError<8>(
const RGBAVector &p1, const RGBAVector &p2,
uint32 bitMask, const RGBAVector &errorMetricVec,
const int pbits[2], uint8 *indices) const;
template double RGBACluster::QuantizedError<16>(
const RGBAVector &p1, const RGBAVector &p2,
uint32 bitMask, const RGBAVector &errorMetricVec,
const int pbits[2], uint8 *indices) const;
uint32 RGBACluster::GetPrincipalAxis(RGBADir &axis, float *eigOne, float *eigTwo) const {
// We use these vectors for calculating the covariance matrix...
RGBAVector toPts[kMaxNumDataPoints];
RGBAVector toPtsMax(-std::numeric_limits<float>::max());
for(uint32 i = 0; i < this->GetNumPoints(); i++) {
toPts[i] = this->GetPoint(i) - this->GetAvg();
for(uint32 j = 0; j < kNumColorChannels; j++) {
toPtsMax[j] = max(toPtsMax[j], toPts[i][j]);
}
}
// Generate a list of unique points...
RGBAVector upts[kMaxNumDataPoints];
uint32 uptsIdx = 0;
for(uint32 i = 0; i < this->GetNumPoints(); i++) {
bool hasPt = false;
for(uint32 j = 0; j < uptsIdx; j++) {
if(upts[j] == this->GetPoint(i))
hasPt = true;
}
if(!hasPt) {
upts[uptsIdx++] = this->GetPoint(i);
}
}
assert(uptsIdx > 0);
if(uptsIdx == 1) {
axis.R() = axis.G() = axis.B() = axis.A() = 0.0f;
return 0;
// Collinear?
} else {
RGBADir dir (upts[1] - upts[0]);
bool collinear = true;
for(uint32 i = 2; i < this->GetNumPoints(); i++) {
RGBAVector v = (upts[i] - upts[0]);
if(fabs(fabs(v*dir) - v.Length()) > 1e-7) {
collinear = false;
break;
}
}
if(collinear) {
axis = dir;
return 0;
}
}
RGBAMatrix covMatrix;
// Compute covariance.
for(uint32 i = 0; i < kNumColorChannels; i++) {
for(uint32 j = 0; j <= i; j++) {
float sum = 0.0;
for(uint32 k = 0; k < this->GetNumPoints(); k++) {
sum += toPts[k][i] * toPts[k][j];
}
covMatrix(i, j) = sum / static_cast<float>(kNumColorChannels - 1);
covMatrix(j, i) = covMatrix(i, j);
}
}
uint32 iters = covMatrix.PowerMethod(axis, eigOne);
if(NULL != eigTwo && NULL != eigOne) {
if(*eigOne != 0.0) {
RGBAMatrix reduced;
for(uint32 j = 0; j < 4; j++) {
for(uint32 i = 0; i < 4; i++) {
reduced(i, j) = axis[j] * axis[i];
}
}
reduced = covMatrix - ((*eigOne) * reduced);
bool allZero = true;
for(uint32 i = 0; i < 16; i++) {
if(fabs(reduced[i]) > 0.0005) {
allZero = false;
}
}
if(allZero) {
*eigTwo = 0.0;
}
else {
RGBADir dummyDir;
iters += reduced.PowerMethod(dummyDir, eigTwo);
}
}
else {
*eigTwo = 0.0;
}
}
return iters;
}
///////////////////////////////////////////////////////////////////////////////
//
// Utility function implementation
//
///////////////////////////////////////////////////////////////////////////////
void ClampEndpoints(RGBAVector &p1, RGBAVector &p2) {
for(uint32 i = 0; i < 4; i++) {
clamp(p1[i], 0.0f, 255.0f);
clamp(p2[i], 0.0f, 255.0f);
}
}

View file

@ -1,238 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
// The original lisence from the code available at the following location:
// http://software.intel.com/en-us/vcsource/samples/fast-texture-compression
//
// This code has been modified significantly from the original.
//--------------------------------------------------------------------------------------
// Copyright 2011 Intel Corporation
// All Rights Reserved
//
// Permission is granted to use, copy, distribute and prepare derivative works of this
// software for any purpose and without fee, provided, that the above copyright notice
// and this statement appear in all copies. Intel makes no representations about the
// suitability of this software for any purpose. THIS SOFTWARE IS PROVIDED "AS IS."
// INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, AND ALL LIABILITY,
// INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE,
// INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not
// assume any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
//
//--------------------------------------------------------------------------------------
#ifndef __RGBA_ENDPOINTS_H__
#define __RGBA_ENDPOINTS_H__
#include "FasTC/TexCompTypes.h"
#include "FasTC/Vector4.h"
#include "FasTC/Matrix4x4.h"
#include "FasTC/Shapes.h"
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cfloat>
#include <cstring>
#include <limits>
static const uint32 kNumColorChannels = 4;
static const uint32 kMaxNumDataPoints = 16;
class RGBAVector : public FasTC::Vector4<float> {
typedef FasTC::Vector4<float> BaseVector;
public:
uint32 GetIdx() const { return m_Idx; }
RGBAVector() : BaseVector(-1.0, -1.0, -1.0, -1.0), m_Idx(0) { }
RGBAVector(uint32 idx, uint32 pixel) :
BaseVector(
static_cast<float>(pixel & 0xFF),
static_cast<float>((pixel >> 8) & 0xFF),
static_cast<float>((pixel >> 16) & 0xFF),
static_cast<float>((pixel >> 24) & 0xFF)
)
, m_Idx(idx)
{ }
RGBAVector(float _r, float _g, float _b, float _a)
: BaseVector(_r, _g, _b, _a), m_Idx(0) { }
explicit RGBAVector(float cc) : BaseVector(cc, cc, cc, cc), m_Idx(0) { }
const float &R() const { return vec[0]; }
float &R() { return vec[0]; }
const float &G() const { return vec[1]; }
float &G() { return vec[1]; }
const float &B() const { return vec[2]; }
float &B() { return vec[2]; }
const float &A() const { return vec[3]; }
float &A() { return vec[3]; }
// Quantize this point.
uint32 ToPixel(const uint32 channelMask = 0xFFFFFFFF, const int pBit = -1) const;
private:
uint32 m_Idx;
};
typedef FasTC::Matrix4x4<float> RGBAMatrix;
class RGBADir : public RGBAVector {
public:
RGBADir() : RGBAVector() { }
RGBADir(const RGBAVector &p) : RGBAVector(p) {
this->Normalize();
}
};
class RGBACluster {
// We really don't ever need to do these
RGBACluster &operator=(const RGBACluster &) { return *this; }
public:
explicit RGBACluster(const uint32 pixels[16])
: m_NumPoints(0)
, m_Avg(0)
, m_Min(std::numeric_limits<float>::max())
, m_Max(-std::numeric_limits<float>::max())
{
for(uint32 i = 0; i < 16; i++) {
RGBAVector p = RGBAVector(i, pixels[i]);
m_Avg += p;
m_PointMap[m_NumPoints] = i;
m_DataPixels[m_NumPoints] = p.ToPixel();
m_DataPoints[m_NumPoints++] = p;
for(uint32 i = 0; i < kNumColorChannels; i++) {
m_Min[i] = std::min(p[i], m_Min[i]);
m_Max[i] = std::max(p[i], m_Max[i]);
}
}
m_Avg /= static_cast<float>(m_NumPoints);
}
RGBAVector &Point(int idx) { return m_DataPoints[m_PointMap[idx]]; }
const RGBAVector &GetPoint(int idx) const {
return m_DataPoints[m_PointMap[idx]];
}
const uint32 &GetPixel(int idx) const {
return m_DataPixels[m_PointMap[idx]];
}
uint32 GetNumPoints() const { return m_NumPoints; }
RGBAVector GetAvg() const { return m_Avg; }
void GetBoundingBox(RGBAVector &Min, RGBAVector &Max) const {
Min = m_Min, Max = m_Max;
}
// Returns the error if we were to quantize the colors right now with the
// given number of buckets and bit mask.
double QuantizedError(
const RGBAVector &p1, const RGBAVector &p2,
uint32 nBuckets, uint32 bitMask, const RGBAVector &errorMetricVec,
const int pbits[2] = NULL, uint8 *indices = NULL) const {
switch(nBuckets) {
case 4: return QuantizedError<4>(p1, p2, bitMask, errorMetricVec, pbits, indices);
case 8: return QuantizedError<8>(p1, p2, bitMask, errorMetricVec, pbits, indices);
case 16: return QuantizedError<16>(p1, p2, bitMask, errorMetricVec, pbits, indices);
}
assert(!"Unsupported num buckets");
return std::numeric_limits<double>::max();
}
bool AllSamePoint() const { return m_Max == m_Min; }
// Returns the principal axis for this point cluster.
uint32 GetPrincipalAxis(RGBADir &axis, float *eigOne, float *eigTwo) const;
void SetShapeIndex(uint32 shapeIdx, uint32 nPartitions) {
m_NumPartitions = nPartitions;
m_ShapeIdx = shapeIdx;
}
void SetShapeIndex(uint32 shapeIdx) {
SetShapeIndex(shapeIdx, m_NumPartitions);
}
void SetPartition(uint32 part) {
m_SelectedPartition = part;
Recalculate();
}
bool IsPointValid(uint32 idx) const {
return m_SelectedPartition ==
BPTCC::GetSubsetForIndex(idx, m_ShapeIdx, m_NumPartitions);
}
private:
// The number of points in the cluster.
uint32 m_NumPoints;
uint32 m_NumPartitions;
uint32 m_SelectedPartition;
uint32 m_ShapeIdx;
RGBAVector m_Avg;
// The points in the cluster.
RGBAVector m_DataPoints[kMaxNumDataPoints];
uint32 m_DataPixels[kMaxNumDataPoints];
uint8 m_PointMap[kMaxNumDataPoints];
RGBAVector m_Min, m_Max;
template<const uint8 nBuckets>
double QuantizedError(
const RGBAVector &p1, const RGBAVector &p2,
uint32 bitMask, const RGBAVector &errorMetricVec,
const int pbits[2] = NULL, uint8 *indices = NULL) const;
void Recalculate() {
m_NumPoints = 0;
m_Avg = RGBAVector(0.0f);
m_Min = RGBAVector(std::numeric_limits<float>::max());
m_Max = RGBAVector(-std::numeric_limits<float>::max());
uint32 map = 0;
for(uint32 idx = 0; idx < 16; idx++) {
if(!IsPointValid(idx)) continue;
m_NumPoints++;
m_Avg += m_DataPoints[idx];
m_PointMap[map++] = idx;
for(uint32 i = 0; i < kNumColorChannels; i++) {
m_Min[i] = std::min(m_DataPoints[idx][i], m_Min[i]);
m_Max[i] = std::max(m_DataPoints[idx][i], m_Max[i]);
}
}
m_Avg /= static_cast<float>(m_NumPoints);
}
};
// Makes sure that the values of the endpoints lie between 0 and 1.
extern void ClampEndpoints(RGBAVector &p1, RGBAVector &p2);
extern uint8 QuantizeChannel(const uint8 val, const uint8 mask, const int pBit = -1);
namespace FasTC {
REGISTER_VECTOR_TYPE(RGBAVector);
REGISTER_VECTOR_TYPE(RGBADir);
}
#endif //__RGBA_ENDPOINTS_H__

View file

@ -1,446 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
// The original lisence from the code available at the following location:
// http://software.intel.com/en-us/vcsource/samples/fast-texture-compression
//
// This code has been modified significantly from the original.
//--------------------------------------------------------------------------------------
// Copyright 2011 Intel Corporation
// All Rights Reserved
//
// Permission is granted to use, copy, distribute and prepare derivative works of this
// software for any purpose and without fee, provided, that the above copyright notice
// and this statement appear in all copies. Intel makes no representations about the
// suitability of this software for any purpose. THIS SOFTWARE IS PROVIDED "AS IS."
// INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, AND ALL LIABILITY,
// INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE,
// INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not
// assume any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
//
//--------------------------------------------------------------------------------------
#include "BC7Config.h"
#include "RGBAEndpointsSIMD.h"
#include "BC7Compressor.h"
#include "BC7CompressionModeSIMD.h"
#include <cassert>
#include <cfloat>
#ifndef HAS_SSE_POPCNT
static inline uint32 popcnt32(uint32 x) {
uint32 m1 = 0x55555555;
uint32 m2 = 0x33333333;
uint32 m3 = 0x0f0f0f0f;
x -= (x>>1) & 1;
x = (x&m2) + ((x>>2)&m2);
x = (x+(x>>4))&m3;
x += x>>8;
return (x+(x>>16)) & 0x3f;
}
#endif
///////////////////////////////////////////////////////////////////////////////
//
// RGBAVectorSIMD implementation
//
///////////////////////////////////////////////////////////////////////////////
/* Original scalar implementation:
// If the mask is all the bits, then we can just return the value.
if(mask == 0xFF) {
return val;
}
uint32 prec = CountBitsInMask(mask);
const uint32 step = 1 << (8 - prec);
assert(step-1 == uint8(~mask));
uint32 lval = val & mask;
uint32 hval = lval + step;
if(pBit >= 0) {
prec++;
lval |= !!(pBit) << (8 - prec);
hval |= !!(pBit) << (8 - prec);
}
if(lval > val) {
lval -= step;
hval -= step;
}
lval |= lval >> prec;
hval |= hval >> prec;
if(sad(val, lval) < sad(val, hval))
return lval;
else
return hval;
*/
// !TODO! AVX2 supports an instruction known as vsllv, which shifts a vector
// by the values stored in another vector. I.e. you can do something like this:
//
// __m128i shiftVals = _mm_set_epi32(1, 2, 3, 4);
// __m128i someVector = _mm_set1_epi32(1) ;
// __m128i shifted = _mm_srav_epi32 (someVector, shiftVals);
//
// and the result will be the same as __mm_Set_epi32(1, 4, 8, 16);
//
// This is useful because our color channels may have different precisions
// when we're quantizing them, such as for BC7 modes 4 and 5. Hence, we would
// want to do our quantization as accurately as possible, but currently it would
// be very hard to vectorize.
#ifdef _MSC_VER
#define ALIGN_SSE __declspec ( align(16) )
#else
#define ALIGN_SSE __attribute__((aligned(16)))
#endif
// Constants. There are two ways to specify them: either by using the _mm_set*
// intrinsics, or by defining them as aligned arrays. You want to do the former
// when you use them infrequently, and the latter when you use them multiple times
// in a short time frame (like in an inner loop)
static const __m128 kZero = _mm_set1_ps(0.0f);
static const __m128 kByteMax = _mm_set1_ps(255.0f);
static const __m128 kHalfVector = _mm_set1_ps(0.5f);
static const __m128i kOneVector = _mm_set1_epi32(1);
static const __m128i kZeroVector = _mm_set1_epi32(0);
static const ALIGN_SSE uint32 kThirtyTwoVector[4] = { 32, 32, 32, 32 };
static const __m128i kByteValMask = _mm_set_epi32(0xFF, 0xFF, 0xFF, 0xFF);
static inline __m128i sad(const __m128i &a, const __m128i &b) {
const __m128i maxab = _mm_max_epu8(a, b);
const __m128i minab = _mm_min_epu8(a, b);
return _mm_and_si128( kByteValMask, _mm_subs_epu8( maxab, minab ) );
}
__m128i RGBAVectorSIMD::ToPixel(const __m128i &qmask) const {
// !SPEED! We should figure out a way to get rid of these scalar operations.
#ifdef HAS_SSE_POPCNT
const uint32 prec = _mm_popcnt_u32(((uint32 *)(&qmask))[0]);
#else
const uint32 prec = popcnt32(((uint32 *)(&qmask))[0]);
#endif
assert(r >= 0.0f && r <= 255.0f);
assert(g >= 0.0f && g <= 255.0f);
assert(b >= 0.0f && b <= 255.0f);
assert(a >= 0.0f && a <= 255.0f);
assert(((uint32 *)(&qmask))[3] == 0xFF || ((uint32 *)(&qmask))[3] == ((uint32 *)(&qmask))[0]);
assert(((uint32 *)(&qmask))[2] == ((uint32 *)(&qmask))[1] && ((uint32 *)(&qmask))[0] == ((uint32 *)(&qmask))[1]);
const __m128i val = _mm_cvtps_epi32( _mm_add_ps(kHalfVector, vec) );
const __m128i step = _mm_slli_epi32( kOneVector, 8 - prec );
const __m128i &mask = qmask;
__m128i lval = _mm_and_si128(val, mask);
__m128i hval = _mm_add_epi32(lval, step);
const __m128i lvalShift = _mm_srli_epi32(lval, prec);
const __m128i hvalShift = _mm_srli_epi32(hval, prec);
lval = _mm_or_si128(lval, lvalShift);
hval = _mm_or_si128(hval, hvalShift);
const __m128i lvald = _mm_sub_epi32( val, lval );
const __m128i hvald = _mm_sub_epi32( hval, val );
const __m128i vd = _mm_cmplt_epi32(lvald, hvald);
__m128i ans = _mm_blendv_epi8(hval, lval, vd);
const __m128i chanExact = _mm_cmpeq_epi32(mask, kByteValMask);
ans = _mm_blendv_epi8( ans, val, chanExact );
return ans;
}
__m128i RGBAVectorSIMD::ToPixel(const __m128i &qmask, const int pBit) const {
// !SPEED! We should figure out a way to get rid of these scalar operations.
#ifdef HAS_SSE_POPCNT
const uint32 prec = _mm_popcnt_u32(((uint32 *)(&qmask))[0]);
#else
const uint32 prec = popcnt32(((uint32 *)(&qmask))[0]);
#endif
assert(r >= 0.0f && r <= 255.0f);
assert(g >= 0.0f && g <= 255.0f);
assert(b >= 0.0f && b <= 255.0f);
assert(a >= 0.0f && a <= 255.0f);
assert(((uint32 *)(&qmask))[3] == 0xFF || ((uint32 *)(&qmask))[3] == ((uint32 *)(&qmask))[0]);
assert(((uint32 *)(&qmask))[2] == ((uint32 *)(&qmask))[1] && ((uint32 *)(&qmask))[0] == ((uint32 *)(&qmask))[1]);
const __m128i val = _mm_cvtps_epi32( _mm_add_ps(kHalfVector, vec) );
const __m128i pbit = _mm_set1_epi32(!!pBit);
const __m128i &mask = qmask; // _mm_set_epi32(alphaMask, channelMask, channelMask, channelMask);
const __m128i step = _mm_slli_epi32( kOneVector, 8 - prec );
__m128i lval = _mm_and_si128( val, mask );
__m128i hval = _mm_add_epi32( lval, step );
const __m128i pBitShifted = _mm_slli_epi32(pbit, 7 - prec);
lval = _mm_or_si128(lval, pBitShifted );
hval = _mm_or_si128(hval, pBitShifted);
// These next three lines we make sure that after adding the pbit that val is
// still in between lval and hval. If it isn't, then we subtract a
// step from both. Now, val should be larger than lval and less than
// hval, but certain situations make this not always the case (e.g. val
// is 0, precision is 4 bits, and pbit is 1). Hence, we add back the
// step if it goes below zero, making it equivalent to hval and so it
// doesn't matter which we choose.
{
__m128i cmp = _mm_cmpgt_epi32(lval, val);
cmp = _mm_mullo_epi32(cmp, step);
lval = _mm_add_epi32(lval, cmp);
hval = _mm_add_epi32(hval, cmp);
cmp = _mm_cmplt_epi32(lval, kZeroVector);
cmp = _mm_mullo_epi32(cmp, step);
lval = _mm_sub_epi32(lval, cmp);
}
const __m128i lvalShift = _mm_srli_epi32(lval, prec + 1);
const __m128i hvalShift = _mm_srli_epi32(hval, prec + 1);
lval = _mm_or_si128(lval, lvalShift);
hval = _mm_or_si128(hval, hvalShift);
const __m128i lvald = _mm_sub_epi32( val, lval );
const __m128i hvald = _mm_sub_epi32( hval, val );
const __m128i vd = _mm_cmplt_epi32(lvald, hvald);
__m128i ans = _mm_blendv_epi8(hval, lval, vd);
const __m128i chanExact = _mm_cmpeq_epi32(mask, kByteValMask);
ans = _mm_blendv_epi8( ans, val, chanExact );
return ans;
}
///////////////////////////////////////////////////////////////////////////////
//
// RGBAMatrixSIMD implementation
//
///////////////////////////////////////////////////////////////////////////////
RGBAVectorSIMD RGBAMatrixSIMD::operator *(const RGBAVectorSIMD &p) const {
__m128 xVec = _mm_set1_ps( p.x );
__m128 yVec = _mm_set1_ps( p.y );
__m128 zVec = _mm_set1_ps( p.z );
__m128 wVec = _mm_set1_ps( p.w );
__m128 vec1 = _mm_mul_ps( xVec, col[0] );
__m128 vec2 = _mm_mul_ps( yVec, col[1] );
__m128 vec3 = _mm_mul_ps( zVec, col[2] );
__m128 vec4 = _mm_mul_ps( wVec, col[3] );
return RGBAVectorSIMD( _mm_add_ps( _mm_add_ps( vec1, vec2 ), _mm_add_ps( vec3, vec4 ) ) );
}
///////////////////////////////////////////////////////////////////////////////
//
// Cluster implementation
//
///////////////////////////////////////////////////////////////////////////////
RGBAClusterSIMD::RGBAClusterSIMD(const RGBAClusterSIMD &left, const RGBAClusterSIMD &right) {
assert(!(left.m_PointBitString & right.m_PointBitString));
*this = left;
for(int i = 0; i < right.m_NumPoints; i++) {
const RGBAVectorSIMD &p = right.m_DataPoints[i];
assert(m_NumPoints < kMaxNumDataPoints);
m_Total += p;
m_DataPoints[m_NumPoints++] = p;
m_Min.vec = _mm_min_ps(m_Min.vec, p.vec);
m_Max.vec = _mm_max_ps(m_Max.vec, p.vec);
}
m_PointBitString = left.m_PointBitString | right.m_PointBitString;
m_PrincipalAxisCached = false;
}
void RGBAClusterSIMD::AddPoint(const RGBAVectorSIMD &p, int idx) {
assert(m_NumPoints < kMaxNumDataPoints);
m_Total += p;
m_DataPoints[m_NumPoints++] = p;
m_PointBitString |= 1 << idx;
m_Min.vec = _mm_min_ps(m_Min.vec, p.vec);
m_Max.vec = _mm_max_ps(m_Max.vec, p.vec);
}
float RGBAClusterSIMD::QuantizedError(const RGBAVectorSIMD &p1, const RGBAVectorSIMD &p2, const uint8 nBuckets, const __m128i &bitMask, const int pbits[2], __m128i *indices) const {
// nBuckets should be a power of two.
assert(!(nBuckets & (nBuckets - 1)));
#ifdef HAS_SSE_POPCNT
const uint8 indexPrec = 8-_mm_popcnt_u32(~(nBuckets - 1) & 0xFF);
#else
const uint8 indexPrec = 8-popcnt32(~(nBuckets - 1) & 0xFF);
#endif
assert(indexPrec >= 2 && indexPrec <= 4);
typedef __m128i tInterpPair[2];
typedef tInterpPair tInterpLevel[16];
const tInterpLevel *interpVals = kBC7InterpolationValuesSIMD + (indexPrec - 1);
__m128i qp1, qp2;
if(pbits) {
qp1 = p1.ToPixel(bitMask, pbits[0]);
qp2 = p2.ToPixel(bitMask, pbits[1]);
}
else {
qp1 = p1.ToPixel(bitMask);
qp2 = p2.ToPixel(bitMask);
}
__m128 errorMetricVec = _mm_load_ps( BC7C::GetErrorMetric() );
__m128 totalError = kZero;
for(int i = 0; i < m_NumPoints; i++) {
const __m128i pixel = m_DataPoints[i].ToPixel( kByteValMask );
__m128 minError = _mm_set1_ps(FLT_MAX);
__m128i bestBucket = _mm_set1_epi32(-1);
for(int j = 0; j < nBuckets; j++) {
const __m128i jVec = _mm_set1_epi32(j);
const __m128i interp0 = (*interpVals)[j][0];
const __m128i interp1 = (*interpVals)[j][1];
const __m128i ip0 = _mm_mullo_epi32( qp1, interp0 );
const __m128i ip1 = _mm_mullo_epi32( qp2, interp1 );
const __m128i ip = _mm_add_epi32( *((const __m128i *)kThirtyTwoVector), _mm_add_epi32( ip0, ip1 ) );
const __m128i dist = sad( _mm_and_si128( _mm_srli_epi32( ip, 6 ), kByteValMask ), pixel );
__m128 errorVec = _mm_cvtepi32_ps( dist );
errorVec = _mm_mul_ps( errorVec, errorMetricVec );
errorVec = _mm_mul_ps( errorVec, errorVec );
errorVec = _mm_hadd_ps( errorVec, errorVec );
errorVec = _mm_hadd_ps( errorVec, errorVec );
const __m128 cmp = _mm_cmple_ps( errorVec, minError );
minError = _mm_blendv_ps( minError, errorVec, cmp );
bestBucket = _mm_blendv_epi8( bestBucket, jVec, _mm_castps_si128( cmp ) );
// Conceptually, once the error starts growing, it doesn't stop growing (we're moving
// farther away from the reference point along the line). Hence we can early out here.
// However, quanitzation artifacts mean that this is not ALWAYS the case, so we do suffer
// about 0.01 RMS error.
if(!((uint8 *)(&cmp))[0])
break;
}
totalError = _mm_add_ps(totalError, minError);
if(indices) ((uint32 *)indices)[i] = ((uint32 *)(&bestBucket))[0];
}
return ((float *)(&totalError))[0];
}
///////////////////////////////////////////////////////////////////////////////
//
// Utility function implementation
//
///////////////////////////////////////////////////////////////////////////////
void ClampEndpoints(RGBAVectorSIMD &p1, RGBAVectorSIMD &p2) {
p1.vec = _mm_min_ps( kByteMax, _mm_max_ps( p1.vec, kZero ) );
p2.vec = _mm_min_ps( kByteMax, _mm_max_ps( p2.vec, kZero ) );
}
void GetPrincipalAxis(const RGBAClusterSIMD &c, RGBADirSIMD &axis) {
if(c.GetNumPoints() == 2) {
axis = c.GetPoint(1) - c.GetPoint(0);
return;
}
RGBAVectorSIMD avg = c.GetTotal();
avg /= float(c.GetNumPoints());
// We use these vectors for calculating the covariance matrix...
RGBAVectorSIMD toPts[kMaxNumDataPoints];
RGBAVectorSIMD toPtsMax(-FLT_MAX);
for(int i = 0; i < c.GetNumPoints(); i++) {
toPts[i] = c.GetPoint(i) - avg;
toPtsMax.vec = _mm_max_ps(toPtsMax.vec, toPts[i].vec);
}
RGBAMatrixSIMD covMatrix;
// Compute covariance.
const float fNumPoints = float(c.GetNumPoints());
for(int i = 0; i < kNumColorChannels; i++) {
for(int j = 0; j <= i; j++) {
float sum = 0.0;
for(int k = 0; k < c.GetNumPoints(); k++) {
sum += toPts[k].c[i] * toPts[k].c[j];
}
covMatrix(i, j) = sum / fNumPoints;
covMatrix(j, i) = covMatrix(i, j);
}
}
// !SPEED! Find eigenvectors by using the power method. This is good because the
// matrix is only 4x4, which allows us to use SIMD...
RGBAVectorSIMD b = toPtsMax;
assert(b.Length() > 0);
b /= b.Length();
RGBAVectorSIMD newB = covMatrix * b;
// !HACK! If the principal eigenvector of the covariance matrix
// converges to zero, that means that the points lie equally
// spaced on a sphere in this space. In this (extremely rare)
// situation, just choose a point and use it as the principal
// direction.
const float newBlen = newB.Length();
if(newBlen < 1e-10) {
axis = toPts[0];
return;
}
for(int i = 0; i < 8; i++) {
newB = covMatrix * b;
newB.Normalize();
b = newB;
}
axis = b;
}

View file

@ -1,397 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
// The original lisence from the code available at the following location:
// http://software.intel.com/en-us/vcsource/samples/fast-texture-compression
//
// This code has been modified significantly from the original.
//--------------------------------------------------------------------------------------
// Copyright 2011 Intel Corporation
// All Rights Reserved
//
// Permission is granted to use, copy, distribute and prepare derivative works of this
// software for any purpose and without fee, provided, that the above copyright notice
// and this statement appear in all copies. Intel makes no representations about the
// suitability of this software for any purpose. THIS SOFTWARE IS PROVIDED "AS IS."
// INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, AND ALL LIABILITY,
// INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE,
// INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not
// assume any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
//
//--------------------------------------------------------------------------------------
#ifndef __RGBA_SIMD_ENDPOINTS_H__
#define __RGBA_SIMD_ENDPOINTS_H__
#include "TexCompTypes.h"
#include <cmath>
#include <cfloat>
#include <cstring>
#include <smmintrin.h>
static const int kNumColorChannels = 4;
static const int kMaxNumDataPoints = 16;
static const __m128 kEpsilonSIMD = _mm_set1_ps(1e-8f);
class RGBAVectorSIMD {
public:
union {
struct { float r, g, b, a; };
struct { float x, y, z, w; };
float c[4];
__m128 vec;
};
RGBAVectorSIMD() : r(-1.0), g(-1.0), b(-1.0), a(-1.0) { }
RGBAVectorSIMD(uint32 pixel) :
r(float(pixel & 0xFF)),
g(float((pixel >> 8) & 0xFF)),
b(float((pixel >> 16) & 0xFF)),
a(float((pixel >> 24) & 0xFF))
{ }
explicit RGBAVectorSIMD(float _r, float _g, float _b, float _a) :
r(_r), g(_g), b(_b), a(_a) { }
explicit RGBAVectorSIMD(float cc) : r(cc), g(cc), b(cc), a(cc) { }
RGBAVectorSIMD (const __m128 &newVec) : vec(newVec) { }
RGBAVectorSIMD (const RGBAVectorSIMD &other) : vec(other.vec) { }
RGBAVectorSIMD operator +(const RGBAVectorSIMD &p) const {
return RGBAVectorSIMD( _mm_add_ps(this->vec, p.vec) );
}
RGBAVectorSIMD &operator +=(const RGBAVectorSIMD &p) {
this->vec = _mm_add_ps(this->vec, p.vec);
return *this;
}
RGBAVectorSIMD operator -(const RGBAVectorSIMD &p) const {
return RGBAVectorSIMD( _mm_sub_ps(this->vec, p.vec) );
}
RGBAVectorSIMD &operator -=(const RGBAVectorSIMD &p) {
this->vec = _mm_sub_ps(this->vec, p.vec);
return *this;
}
RGBAVectorSIMD operator /(const float s) const {
return RGBAVectorSIMD( _mm_div_ps(this->vec, _mm_set1_ps(s) ) );
}
RGBAVectorSIMD &operator /=(const float s) {
this->vec = _mm_div_ps(this->vec, _mm_set1_ps(s) );
return *this;
}
float operator *(const RGBAVectorSIMD &p) const {
__m128 mul = _mm_mul_ps(this->vec, p.vec);
mul = _mm_hadd_ps(mul, mul);
mul = _mm_hadd_ps(mul, mul);
return ((float *)(&mul))[0];
}
void Normalize() {
__m128 rsqrt = _mm_rsqrt_ps( _mm_set1_ps( (*this) * (*this) ) );
vec = _mm_mul_ps( vec, rsqrt );
}
float Length() const {
return sqrt((*this) * (*this));
}
RGBAVectorSIMD &operator *=(const RGBAVectorSIMD &v) {
this->vec = _mm_mul_ps(this->vec, v.vec);
return *this;
}
RGBAVectorSIMD operator *(const float s) const {
return RGBAVectorSIMD( _mm_mul_ps( this->vec, _mm_set1_ps(s) ) );
}
friend RGBAVectorSIMD operator *(const float s, const RGBAVectorSIMD &p) {
return RGBAVectorSIMD( _mm_mul_ps( p.vec, _mm_set1_ps(s) ) );
}
RGBAVectorSIMD &operator *=(const float s) {
this->vec = _mm_mul_ps( this->vec, _mm_set1_ps(s) );
return *this;
}
float &operator [](const int i) {
return c[i];
}
friend bool operator ==(const RGBAVectorSIMD &rhs, const RGBAVectorSIMD &lhs) {
__m128 d = _mm_sub_ps(rhs.vec, lhs.vec);
d = _mm_mul_ps(d, d);
__m128 cmp = _mm_cmpgt_ps(d, kEpsilonSIMD);
cmp = _mm_hadd_ps(cmp, cmp);
cmp = _mm_hadd_ps(cmp, cmp);
return ((float *)(&cmp))[0] == 0.0f;
}
friend bool operator !=(const RGBAVectorSIMD &rhs, const RGBAVectorSIMD &lhs) {
return !(rhs == lhs);
}
operator float *() {
return c;
}
// Quantize this point.
__m128i ToPixel(const __m128i &channelMask, const int pBit) const;
__m128i ToPixel(const __m128i &channelMask) const;
};
class RGBAMatrixSIMD {
private:
union {
float m[kNumColorChannels*kNumColorChannels];
struct {
float m1, m5, m9, m13;
float m2, m6, m10, m14;
float m3, m7, m11, m15;
float m4, m8, m12, m16;
};
__m128 col[kNumColorChannels];
};
RGBAMatrixSIMD(const float *arr) {
memcpy(m, arr, sizeof(m));
}
RGBAMatrixSIMD(const __m128 newcol[kNumColorChannels]) {
for(int i = 0; i < kNumColorChannels; i++)
col[i] = newcol[i];
}
public:
RGBAMatrixSIMD() :
m1(1.0f), m2(0.0f), m3(0.0f), m4(0.0f),
m5(0.0f), m6(1.0f), m7(0.0f), m8(0.0f),
m9(0.0f), m10(0.0f), m11(1.0f), m12(0.0f),
m13(0.0f), m14(0.0f), m15(0.0f), m16(1.0f)
{ }
RGBAMatrixSIMD &operator =(const RGBAMatrixSIMD &other) {
memcpy(m, other.m, sizeof(m));
return (*this);
}
RGBAMatrixSIMD operator +(const RGBAMatrixSIMD &p) const {
RGBAMatrixSIMD newm;
for(int i = 0; i < kNumColorChannels; i++) {
newm.col[i] = _mm_add_ps(col[i], p.col[i]);
}
return newm;
}
RGBAMatrixSIMD &operator +=(const RGBAMatrixSIMD &p) {
for(int i = 0; i < kNumColorChannels; i++) {
col[i] = _mm_add_ps( col[i], p.col[i] );
}
return *this;
}
RGBAMatrixSIMD operator -(const RGBAMatrixSIMD &p) const {
RGBAMatrixSIMD newm;
for(int i = 0; i < kNumColorChannels; i++) {
newm.col[i] = _mm_sub_ps( col[i], p.col[i] );
}
return newm;
}
RGBAMatrixSIMD &operator -=(const RGBAMatrixSIMD &p) {
for(int i = 0; i < kNumColorChannels; i++) {
col[i] = _mm_sub_ps( col[i], p.col[i] );
}
return *this;
}
RGBAMatrixSIMD operator /(const float s) const {
__m128 f = _mm_set1_ps(s);
RGBAMatrixSIMD newm;
for(int i = 0; i < kNumColorChannels; i++) {
newm.col[i] = _mm_div_ps( col[i], f );
}
return newm;
}
RGBAMatrixSIMD &operator /=(const float s) {
__m128 f = _mm_set1_ps(s);
for(int i = 0; i < kNumColorChannels; i++) {
col[i] = _mm_div_ps(col[i], f);
}
return *this;
}
RGBAMatrixSIMD operator *(const float s) const {
__m128 f = _mm_set1_ps(s);
RGBAMatrixSIMD newm;
for(int i = 0; i < kNumColorChannels; i++) {
newm.col[i] = _mm_mul_ps( col[i], f );
}
return newm;
}
friend RGBAMatrixSIMD operator *(const float s, const RGBAMatrixSIMD &p) {
__m128 f = _mm_set1_ps(s);
RGBAMatrixSIMD newm;
for(int i = 0; i < kNumColorChannels; i++) {
newm.col[i] = _mm_mul_ps( p.col[i], f );
}
return newm;
}
RGBAMatrixSIMD &operator *=(const float s) {
__m128 f = _mm_set1_ps(s);
for(int i = 0; i < kNumColorChannels; i++)
col[i] = _mm_mul_ps(col[i], f);
return *this;
}
float &operator ()(const int i, const int j) {
return (*this)[j*4 + i];
}
float &operator [](const int i) {
return m[i];
}
friend bool operator ==(const RGBAMatrixSIMD &rhs, const RGBAMatrixSIMD &lhs) {
__m128 sum = _mm_set1_ps(0.0f);
for(int i = 0; i < kNumColorChannels; i++) {
__m128 d = _mm_sub_ps(rhs.col[i], lhs.col[i]);
d = _mm_mul_ps(d, d);
__m128 cmp = _mm_cmpgt_ps(d, kEpsilonSIMD);
cmp = _mm_hadd_ps(cmp, cmp);
cmp = _mm_hadd_ps(cmp, cmp);
sum = _mm_add_ps(sum, cmp);
}
if(((float *)(&sum))[0] != 0)
return false;
else
return true;
}
operator float *() {
return m;
}
RGBAVectorSIMD operator *(const RGBAVectorSIMD &p) const;
};
class RGBADirSIMD : public RGBAVectorSIMD {
public:
RGBADirSIMD() : RGBAVectorSIMD() { }
RGBADirSIMD(const RGBAVectorSIMD &p) : RGBAVectorSIMD(p) {
this->Normalize();
}
};
// Makes sure that the values of the endpoints lie between 0 and 1.
extern void ClampEndpoints(RGBAVectorSIMD &p1, RGBAVectorSIMD &p2);
class RGBAClusterSIMD {
public:
RGBAClusterSIMD() :
m_NumPoints(0), m_Total(0.0f),
m_PointBitString(0),
m_Min(FLT_MAX),
m_Max(-FLT_MAX),
m_PrincipalAxisCached(false)
{ }
RGBAClusterSIMD(const RGBAClusterSIMD &c) :
m_NumPoints(c.m_NumPoints),
m_Total(c.m_Total),
m_PointBitString(c.m_PointBitString),
m_Min(c.m_Min),
m_Max(c.m_Max),
m_PrincipalAxisCached(false)
{
memcpy(this->m_DataPoints, c.m_DataPoints, m_NumPoints * sizeof(RGBAVectorSIMD));
}
RGBAClusterSIMD(const RGBAClusterSIMD &left, const RGBAClusterSIMD &right);
RGBAClusterSIMD(const RGBAVectorSIMD &p, int idx) :
m_NumPoints(1),
m_Total(p),
m_PointBitString(0),
m_Min(p), m_Max(p),
m_PrincipalAxisCached(false)
{
m_DataPoints[0] = p;
m_PointBitString |= (1 << idx);
}
RGBAVectorSIMD GetTotal() const { return m_Total; }
const RGBAVectorSIMD &GetPoint(int idx) const { return m_DataPoints[idx]; }
int GetNumPoints() const { return m_NumPoints; }
RGBAVectorSIMD GetAvg() const { return m_Total / float(m_NumPoints); }
void AddPoint(const RGBAVectorSIMD &p, int idx);
void GetBoundingBox(RGBAVectorSIMD &Min, RGBAVectorSIMD &Max) const {
Min = m_Min, Max = m_Max;
}
// Returns the error if we were to quantize the colors right now with the given number of buckets and bit mask.
float QuantizedError(const RGBAVectorSIMD &p1, const RGBAVectorSIMD &p2, const uint8 nBuckets, const __m128i &bitMask, const int pbits[2] = NULL, __m128i *indices = NULL) const;
bool AllSamePoint() const { return m_Max == m_Min; }
int GetPointBitString() const { return m_PointBitString; }
private:
// The number of points in the cluster.
int m_NumPoints;
RGBAVectorSIMD m_Total;
// The points in the cluster.
RGBAVectorSIMD m_DataPoints[kMaxNumDataPoints];
RGBAVectorSIMD m_Min, m_Max;
int m_PointBitString;
RGBADirSIMD m_PrincipalAxis;
bool m_PrincipalAxisCached;
};
extern void GetPrincipalAxis(const RGBAClusterSIMD &c, RGBADirSIMD &axis);
#endif //__RGBA_SIMD_ENDPOINTS_H__

View file

@ -1,58 +0,0 @@
# Copyright 2016 The University of North Carolina at Chapel Hill
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Please send all BUG REPORTS to <pavel@cs.unc.edu>.
# <http://gamma.cs.unc.edu/FasTC/>
INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/Base/include )
INCLUDE_DIRECTORIES( ${FasTC_BINARY_DIR}/Base/include )
INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/Core/include )
INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/IO/include )
ADD_EXECUTABLE(
tc
"src/tc.cpp"
)
ADD_EXECUTABLE(
compare
"src/compare.cpp"
)
ADD_EXECUTABLE(
decomp
"src/decomp.cpp"
)
# Add flag for link time code generation. This was used to build the libpng
# libraries, so we should probably also include it for this project as well...
IF( MSVC )
SET_TARGET_PROPERTIES(tc PROPERTIES LINK_FLAGS "/LTCG")
SET_TARGET_PROPERTIES(compare PROPERTIES LINK_FLAGS "/LTCG")
SET_TARGET_PROPERTIES(decomp PROPERTIES LINK_FLAGS "/LTCG")
ENDIF()
TARGET_LINK_LIBRARIES( tc FasTCBase )
TARGET_LINK_LIBRARIES( tc FasTCIO )
TARGET_LINK_LIBRARIES( tc FasTCCore )
TARGET_LINK_LIBRARIES( compare FasTCBase )
TARGET_LINK_LIBRARIES( compare FasTCIO )
TARGET_LINK_LIBRARIES( decomp FasTCBase )
TARGET_LINK_LIBRARIES( decomp FasTCIO )
INSTALL(TARGETS tc compare decomp EXPORT FasTCTargets
RUNTIME DESTINATION bin COMPONENT bin)

View file

@ -1,130 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#define _CRT_SECURE_NO_WARNINGS
#include <cassert>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <iostream>
#include <fstream>
#ifdef _MSC_VER
# include <SDKDDKVer.h>
# include <Windows.h>
#endif
#include "FasTC/Image.h"
#include "FasTC/ImageFile.h"
#include "FasTC/TexComp.h"
#include "FasTC/ThreadSafeStreambuf.h"
static void PrintUsageAndExit() {
fprintf(stderr, "Usage: compare [-d] <img1> <img2>\n");
exit(1);
}
void gen_random(char *s, const int len) {
static const char alphanum[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
srand(static_cast<unsigned int>(time(NULL)));
for (int i = 0; i < len; ++i) {
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
}
s[len] = 0;
}
int main(int argc, char **argv) {
if(argc < 3 || argc > 5) {
PrintUsageAndExit();
}
bool diff_images = false;
float diff_multiplier = 1.0;
int arg = 1;
if (strncmp(argv[arg], "-d", 2) == 0) {
diff_images = true;
arg++;
if (argc == 5) {
diff_multiplier = static_cast<float>(atoi(argv[arg]));
if (diff_multiplier < 0) {
PrintUsageAndExit();
}
arg++;
}
}
ImageFile img1f (argv[arg]);
if(!img1f.Load()) {
fprintf(stderr, "Error loading file: %s\n", argv[arg]);
return 1;
}
arg++;
ImageFile img2f (argv[arg]);
if(!img2f.Load()) {
fprintf(stderr, "Error loading file: %s\n", argv[arg]);
return 1;
}
arg++;
FasTC::Image<> &img1 = *img1f.GetImage();
FasTC::Image<> &img2 = *img2f.GetImage();
if (img1.GetWidth() != img2.GetWidth() ||
img1.GetHeight() != img2.GetHeight()) {
std::cerr << "Images differ in dimension!" << std::endl;
return 1;
}
if (diff_images) {
FasTC::Image<> diff = img1.Diff(&img2, diff_multiplier);
char fname_buf [5 + 16 + 4 + 1]; // "diff-" + hash + ".png" + null
memset(fname_buf, 0, sizeof(fname_buf));
strncat(fname_buf, "diff-", 5);
gen_random(fname_buf + 5, 16);
strncat(fname_buf + 5 + 16, ".png", 4);
EImageFileFormat fmt = ImageFile::DetectFileFormat(fname_buf);
ImageFile cImgFile (fname_buf, fmt, diff);
cImgFile.Write();
}
double PSNR = img1.ComputePSNR(&img2);
if(PSNR > 0.0) {
fprintf(stdout, "PSNR: %.3f\n", PSNR);
}
else {
fprintf(stderr, "Error computing PSNR\n");
}
double SSIM = img1.ComputeSSIM(&img2);
if(SSIM > 0.0) {
fprintf(stdout, "SSIM: %.9f\n", SSIM);
} else {
fprintf(stderr, "Error computing MSSIM\n");
}
return 0;
}

View file

@ -1,58 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#define _CRT_SECURE_NO_WARNINGS
#include <cassert>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <fstream>
#ifdef _MSC_VER
# include <SDKDDKVer.h>
# include <Windows.h>
#endif
#include "FasTC/Image.h"
#include "FasTC/ImageFile.h"
#include "FasTC/TexComp.h"
#include "FasTC/ThreadSafeStreambuf.h"
void PrintUsage() {
fprintf(stderr, "Usage: decomp <in_img> <out_img>\n");
fprintf(stderr, "\tIf in_img is not a compressed image, then this tool simply copies the image.\n");
}
int main(int argc, char **argv) {
if(argc != 3) {
return 1;
}
ImageFile imgf (argv[1]);
if(!imgf.Load()) {
return 1;
}
FasTC::Image<> *img = imgf.GetImage();
EImageFileFormat fmt = ImageFile::DetectFileFormat(argv[2]);
ImageFile cImgFile (argv[2], fmt, *img);
cImgFile.Write();
return 0;
}

View file

@ -1,346 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#define _CRT_SECURE_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <fstream>
#ifdef _MSC_VER
# include <SDKDDKVer.h>
# include <Windows.h>
# undef min
# undef max
#endif
#include "FasTC/Image.h"
#include "FasTC/ImageFile.h"
#include "FasTC/TexComp.h"
#include "FasTC/ThreadSafeStreambuf.h"
void PrintUsage() {
fprintf(stderr, "Usage: tc [OPTIONS] imagefile\n");
fprintf(stderr, "\n");
fprintf(stderr, "\t-h|--help\tPrint this help.\n");
fprintf(stderr, "\t-v\t\tVerbose mode: prints out Entropy, Mean Local Entropy, and MSSIM\n");
fprintf(stderr, "\t-f <fmt>\tFormat to use. Either \"BPTC\", \"ETC1\", \"DXT1\", \"DXT5\", or \"PVRTC\". Default: BPTC\n");
fprintf(stderr, "\t-l\t\tSave an output log.\n");
fprintf(stderr, "\t-d <file>\tSpecify decompressed output (default: basename-<fmt>.png)\n");
fprintf(stderr, "\t-nd\t\tSuppress decompressed output\n");
fprintf(stderr, "\t-q <quality>\tSet compression quality level. Default: 50\n");
fprintf(stderr, "\t-n <num>\tCompress the image num times and give the average time and PSNR. Default: 1\n");
fprintf(stderr, "\t-simd\t\tUse SIMD compression path\n");
fprintf(stderr, "\t-t <num>\tCompress the image using <num> threads. Default: 1\n");
fprintf(stderr, "\t-a \t\tCompress the image using synchronization via atomic operations. Default: Off\n");
fprintf(stderr, "\t-j <num>\tUse <num> blocks for each work item in a worker queue threading model. Default: (Blocks / Threads)\n");
}
void ExtractBasename(const char *filename, char *buf, size_t bufSz) {
size_t len = strlen(filename);
const char *end = filename + len;
const char *ext = end;
const char *base = NULL;
while(--end != filename && !base) {
if(*end == '.') {
ext = end;
} else if(*end == '\\' || *end == '/') {
base = end + 1;
}
}
if (!base) {
base = end;
}
size_t numChars = ext - base + 1;
size_t toCopy = ::std::min(numChars, bufSz);
memcpy(buf, base, toCopy);
buf[toCopy - 1] = '\0';
return;
}
int main(int argc, char **argv) {
int fileArg = 1;
if (fileArg == argc) {
PrintUsage();
exit(1);
}
char decompressedOutput[256];
decompressedOutput[0] = '\0';
bool bDecompress = true;
int numJobs = 0;
int quality = 50;
int numThreads = 1;
int numCompressions = 1;
bool bUseSIMD = false;
bool bSaveLog = false;
bool bUseAtomics = false;
bool bUsePVRTexLib = false;
bool bUseNVTT = false;
bool bVerbose = false;
FasTC::ECompressionFormat format = FasTC::eCompressionFormat_BPTC;
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], "-f") == 0) {
fileArg++;
if (fileArg == argc) {
PrintUsage();
exit(1);
} else {
if (!strcmp(argv[fileArg], "PVRTC")) {
format = FasTC::eCompressionFormat_PVRTC4;
} else if (!strcmp(argv[fileArg], "PVRTCLib")) {
format = FasTC::eCompressionFormat_PVRTC4;
bUsePVRTexLib = true;
} else if (!strcmp(argv[fileArg], "BPTCLib")) {
format = FasTC::eCompressionFormat_BPTC;
bUseNVTT = true;
} else if (!strcmp(argv[fileArg], "ETC1")) {
format = FasTC::eCompressionFormat_ETC1;
} else if (!strcmp(argv[fileArg], "DXT1")) {
format = FasTC::eCompressionFormat_DXT1;
} else if (!strcmp(argv[fileArg], "DXT5")) {
format = FasTC::eCompressionFormat_DXT5;
}
}
fileArg++;
knowArg = true;
continue;
}
if (strcmp(argv[fileArg], "-h") == 0 || strcmp(argv[fileArg], "--help") == 0) {
PrintUsage();
exit(0);
}
if (strcmp(argv[fileArg], "-d") == 0) {
fileArg++;
if (fileArg == argc) {
PrintUsage();
exit(1);
} else {
size_t sz = 255;
sz = ::std::min(sz, static_cast<size_t>(strlen(argv[fileArg])));
memcpy(decompressedOutput, argv[fileArg], sz + 1);
}
fileArg++;
knowArg = true;
continue;
}
if (strcmp(argv[fileArg], "-nd") == 0) {
fileArg++;
bDecompress = false;
knowArg = true;
continue;
}
if (strcmp(argv[fileArg], "-l") == 0) {
fileArg++;
bSaveLog = true;
knowArg = true;
continue;
}
if (strcmp(argv[fileArg], "-v") == 0) {
fileArg++;
bVerbose = 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;
}
if (strcmp(argv[fileArg], "-a") == 0) {
fileArg++;
bUseAtomics = true;
knowArg = true;
continue;
}
} while (knowArg && fileArg < argc);
if (fileArg == argc) {
PrintUsage();
exit(1);
}
char basename[256];
ExtractBasename(argv[fileArg], basename, 256);
ImageFile file(argv[fileArg]);
if (!file.Load()) {
return 1;
}
FasTC::Image<> img(*file.GetImage());
if (bVerbose) {
fprintf(stdout, "Entropy: %.5f\n", img.ComputeEntropy());
fprintf(stdout, "Mean Local Entropy: %.5f\n", img.ComputeMeanLocalEntropy());
}
std::ofstream logFile;
ThreadSafeStreambuf streamBuf(logFile);
std::ostream logStream(&streamBuf);
if (bSaveLog) {
char logname[256];
sprintf(logname, "%s.log", basename);
logFile.open(logname);
}
SCompressionSettings settings;
settings.format = format;
settings.bUseSIMD = bUseSIMD;
settings.bUseAtomics = bUseAtomics;
settings.iNumThreads = numThreads;
settings.iQuality = quality;
settings.iNumCompressions = numCompressions;
settings.iJobSize = numJobs;
settings.bUsePVRTexLib = bUsePVRTexLib;
settings.bUseNVTT = bUseNVTT;
if (bSaveLog) {
settings.logStream = &logStream;
} else {
settings.logStream = NULL;
}
CompressedImage *ci = CompressImage(&img, settings);
if (NULL == ci) {
return 1;
}
if (ci->GetWidth() != img.GetWidth() ||
ci->GetHeight() != img.GetHeight()) {
fprintf(stderr, "Cannot compute image metrics: compressed and uncompressed dimensions differ.\n");
} else {
double PSNR = img.ComputePSNR(ci);
if(PSNR > 0.0) {
fprintf(stdout, "PSNR: %.3f\n", PSNR);
}
else {
fprintf(stderr, "Error computing PSNR\n");
}
if(bVerbose) {
double SSIM = img.ComputeSSIM(ci);
if(SSIM > 0.0) {
fprintf(stdout, "SSIM: %.9f\n", SSIM);
} else {
fprintf(stderr, "Error computing SSIM\n");
}
}
}
if(bDecompress) {
if(decompressedOutput[0] != '\0') {
memcpy(basename, decompressedOutput, 256);
} else if(format == FasTC::eCompressionFormat_BPTC) {
strcat(basename, "-bptc.png");
} else if(format == FasTC::eCompressionFormat_PVRTC4) {
strcat(basename, "-pvrtc-4bpp.png");
} else if(format == FasTC::eCompressionFormat_DXT1) {
strcat(basename, "-dxt1.png");
} else if(format == FasTC::eCompressionFormat_DXT5) {
strcat(basename, "-dxt5.png");
} else if(format == FasTC::eCompressionFormat_ETC1) {
strcat(basename, "-etc1.png");
}
EImageFileFormat fmt = ImageFile::DetectFileFormat(basename);
ImageFile cImgFile (basename, fmt, *ci);
cImgFile.Write();
}
// Cleanup
delete ci;
if(bSaveLog) {
logFile.close();
}
return 0;
}

View file

@ -73,11 +73,6 @@ IF(TREAT_WARNINGS_AS_ERRORS)
ENDIF(MSVC)
ENDIF(TREAT_WARNINGS_AS_ERRORS)
SET(CMAKE_MODULE_PATH "${FasTC_SOURCE_DIR}/CMakeModules" ${CMAKE_MODULE_PATH})
FIND_PACKAGE(PVRTexLib)
FIND_PACKAGE(BC7Export)
FIND_PACKAGE(PNG)
######################################################################
##
## Package definitions
@ -89,66 +84,11 @@ SET(LIB_INSTALL_DIR lib CACHE INTERNAL "")
SET(BIN_INSTALL_DIR bin CACHE INTERNAL "")
SET(FASTC_DIRECTORIES
Base Core IO BPTCEncoder PVRTCEncoder DXTEncoder ETCEncoder ASTCEncoder
Base ASTCEncoder
)
FOREACH(DIR ${FASTC_DIRECTORIES})
ADD_SUBDIRECTORY(${DIR})
ENDFOREACH()
ADD_SUBDIRECTORY(CLTool)
SET(FasTC_LIBRARIES FasTCBase FasTCIO FasTCCore BPTCEncoder PVRTCEncoder DXTEncoder ETCEncoder ASTCEncoder)
SET(FasTC_EXECUTABLES tc compare decomp)
######################################################################
##
## Config
##
######################################################################
INCLUDE(CMakePackageConfigHelpers)
CONFIGURE_PACKAGE_CONFIG_FILE(
"${FasTC_SOURCE_DIR}/CMakeModules/FasTCConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/FasTCConfig.cmake"
INSTALL_DESTINATION ${LIB_INSTALL_DIR}/cmake/FasTC
PATH_VARS INCLUDE_INSTALL_DIR BIN_INSTALL_DIR LIB_INSTALL_DIR)
WRITE_BASIC_PACKAGE_VERSION_FILE(
"${CMAKE_CURRENT_BINARY_DIR}/FasTCConfigVersion.cmake"
VERSION ${FasTC_VERSION}
COMPATIBILITY SameMajorVersion)
INSTALL(
FILES "${CMAKE_CURRENT_BINARY_DIR}/FasTCConfigVersion.cmake" "${CMAKE_CURRENT_BINARY_DIR}/FasTCConfig.cmake"
DESTINATION ${LIB_INSTALL_DIR}/cmake/FasTC
COMPONENT dev)
EXPORT(
TARGETS ${FasTC_LIBRARIES} ${FasTC_EXECUTABLES}
FILE "${CMAKE_CURRENT_BINARY_DIR}/FasTCTargets.cmake")
EXPORT(PACKAGE FasTC)
INSTALL(
EXPORT FasTCTargets
FILE FasTCTargets.cmake
DESTINATION ${LIB_INSTALL_DIR}/cmake/FasTC)
######################################################################
##
## Testing
##
######################################################################
ENABLE_TESTING()
IF(MSVC)
SET(gtest_force_shared_crt TRUE CACHE BOOL "Used to properly select MSVC runtime libraries" FORCE)
ENDIF(MSVC)
ADD_SUBDIRECTORY(GTest)
FOREACH(DIR ${FASTC_DIRECTORIES})
SET(TESTDIR ${FasTC_SOURCE_DIR}/${DIR}/test)
IF(IS_DIRECTORY ${TESTDIR})
ADD_SUBDIRECTORY(${TESTDIR})
ENDIF()
ENDFOREACH()
SET(FasTC_LIBRARIES FasTCBase ASTCEncoder)

View file

@ -1,53 +0,0 @@
# Copyright 2016 The University of North Carolina at Chapel Hill
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Please send all BUG REPORTS to <pavel@cs.unc.edu>.
# <http://gamma.cs.unc.edu/FasTC/>
SET(FASTC_VERSION @FasTC_VERSION@)
@PACKAGE_INIT@
SET(FasTC_LIBRARIES FasTCBase FasTCIO FasTCCore BPTCEncoder PVRTCEncoder DXTEncoder ETCEncoder ASTCEncoder)
IF(NOT TARGET FasTCBase)
# We're coming from a build tree -- include all of the targets
# from the project and try to make sure that our includes are set properly
INCLUDE("${CMAKE_CURRENT_LIST_DIR}/FasTCTargets.cmake")
FOREACH(LIB ${FasTC_LIBRARIES})
STRING(REPLACE "FasTC" "" DIR "${LIB}")
SET(CURRENT_DIR "@FasTC_SOURCE_DIR@/${DIR}/include")
IF( EXISTS "${CURRENT_DIR}/" )
SET(FasTC_INCLUDE_DIRS ${FasTC_INCLUDE_DIRS} ${CURRENT_DIR})
ENDIF()
SET(CURRENT_DIR "@FasTC_BINARY_DIR@/${DIR}/include")
IF( EXISTS "${CURRENT_DIR}/" )
SET(FasTC_INCLUDE_DIRS ${FasTC_INCLUDE_DIRS} ${CURRENT_DIR})
ENDIF()
ENDFOREACH()
SET(FasTC_EXECUTABLES tc compare decomp)
ELSE()
# This is an install tree -- everything should be a lot easier....
SET_AND_CHECK(FasTC_INCLUDE_DIRS "@PACKAGE_INCLUDE_INSTALL_DIR@/FasTC")
SET_AND_CHECK(FasTC_BIN_DIR "@PACKAGE_BIN_INSTALL_DIR@")
SET_AND_CHECK(FasTC_LIB_DIR "@PACKAGE_LIB_INSTALL_DIR@")
ENDIF()

View file

@ -1,28 +0,0 @@
# Copyright 2016 The University of North Carolina at Chapel Hill
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Please send all BUG REPORTS to <pavel@cs.unc.edu>.
# <http://gamma.cs.unc.edu/FasTC/>
SET(PACKAGE_VERSION "@FasTC_VERSION@")
# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()

View file

@ -1,38 +0,0 @@
# Copyright 2016 The University of North Carolina at Chapel Hill
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Please send all BUG REPORTS to <pavel@cs.unc.edu>.
# <http://gamma.cs.unc.edu/FasTC/>
# - Try to find libPVRTexLib
# Once done this will define
# PVRTEXLIB_FOUND - System has PVRTexLib
# PVRTEXLIB_INCLUDE_DIRS - The PVRTexLib include directories
# PVRTEXLIB_LIBRARIES - The libraries needed to use PVRTexLib
SET(AVPCLLIB_ROOT "" CACHE STRING "Location of the BC7 Export library from NVTT")
IF(NOT AVPCLLIB_ROOT STREQUAL "")
IF(NOT EXISTS "${AVPCLLIB_ROOT}/src/CMakeLists.txt")
CONFIGURE_FILE(
"${CMAKE_CURRENT_LIST_DIR}/bc7_export/CMakeLists.txt"
"${AVPCLLIB_ROOT}/src"
COPYONLY)
ENDIF()
ADD_SUBDIRECTORY(${AVPCLLIB_ROOT}/src ${CMAKE_CURRENT_BINARY_DIR}/bc7_export)
set(AVPCLLIB_INCLUDE_DIR ${AVPCLLIB_ROOT}/src )
SET(FOUND_NVTT_BPTC_EXPORT TRUE)
ENDIF()
mark_as_advanced( FORCE AVPCLLIB_ROOT AVPCLLIB_INCLUDE_DIR )

View file

@ -1,96 +0,0 @@
# Copyright 2016 The University of North Carolina at Chapel Hill
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Please send all BUG REPORTS to <pavel@cs.unc.edu>.
# <http://gamma.cs.unc.edu/FasTC/>
# - Try to find libPVRTexLib
# Once done this will define
# PVRTEXLIB_FOUND - System has PVRTexLib
# PVRTEXLIB_INCLUDE_DIRS - The PVRTexLib include directories
# PVRTEXLIB_LIBRARIES - The libraries needed to use PVRTexLib
IF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
SET( PVRTEXLIB_ROOT "/Applications/Imagination/PowerVR/GraphicsSDK/PVRTexTool/Library" )
find_path(
PVRTEXLIB_INCLUDE_DIR PVRTexture.h
PATHS ${PVRTEXLIB_ROOT}/Include
)
find_library(PVRTEXLIB_LIB PVRTexLib
PATHS ${PVRTEXLIB_ROOT}/OSX_x86/Static
${PVRTEXLIB_ROOT}/OSX_x86/Dynamic
)
SET( USE_PTHREAD TRUE )
ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
SET( PVRTEXLIB_ROOT "/opt/Imagination/PowerVR/GraphicsSDK/PVRTexTool/Library" )
find_path(
PVRTEXLIB_INCLUDE_DIR PVRTexture.h
PATHS ${PVRTEXLIB_ROOT}/Include
)
IF(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
find_library(PVRTEXLIB_LIB PVRTexLib
PATHS ${PVRTEXLIB_ROOT}/Linux_x86_64/Static
${PVRTEXLIB_ROOT}/Linux_x86_64/Dynamic
)
ELSE()
find_library(PVRTEXLIB_LIB PVRTexLib
PATHS ${PVRTEXLIB_ROOT}/Linux_x86_32/Static
${PVRTEXLIB_ROOT}/Linux_x86_32/Dynamic
)
ENDIF()
SET( USE_PTHREAD TRUE )
ELSEIF(MSVC)
SET( PVRTEXLIB_ROOT "C:/Imagination/PowerVR/GraphicsSDK/PVRTexTool/Library" )
find_path(
PVRTEXLIB_INCLUDE_DIR PVRTexture.h
PATHS ${PVRTEXLIB_ROOT}/Include
)
IF(${CMAKE_GENERATOR} MATCHES Win64)
find_library(PVRTEXLIB_LIB PVRTexLib
PATHS ${PVRTEXLIB_ROOT}/Windows_x86_64/Static
${PVRTEXLIB_ROOT}/Windows_x86_64/Dynamic
)
ELSE()
find_library(PVRTEXLIB_LIB PVRTexLib
PATHS ${PVRTEXLIB_ROOT}/Windows_x86_32/Static
${PVRTEXLIB_ROOT}/Windows_x86_32/Dynamic
)
ENDIF()
ENDIF()
IF( USE_PTHREAD )
FIND_PACKAGE( Threads REQUIRED )
set(PVRTEXLIB_LIBRARIES
${PVRTEXLIB_LIB}
${CMAKE_THREAD_LIBS_INIT}
)
ELSE()
set(PVRTEXLIB_LIBRARIES ${PVRTEXLIB_LIB})
ENDIF()
set(PVRTEXLIB_INCLUDE_DIRS ${PVRTEXLIB_INCLUDE_DIR} )
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set LIBXML2_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(PVRTexLib DEFAULT_MSG
PVRTEXLIB_LIB PVRTEXLIB_INCLUDE_DIR)
mark_as_advanced( PVRTEXLIB_ROOT PVRTEXLIB_INCLUDE_DIR PVRTEXLIB_LIB )

View file

@ -1,79 +0,0 @@
# Copyright 2016 The University of North Carolina at Chapel Hill
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Please send all BUG REPORTS to <pavel@cs.unc.edu>.
# <http://gamma.cs.unc.edu/FasTC/>
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_LIST_DIR})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_LIST_DIR}/arvo)
SET( HEADERS
avpcl.h
bits.h
endpts.h
ImfArray.h
rgba.h
shapes_three.h
shapes_two.h
targa.h
tile.h
utils.h
arvo/ArvoMath.h
arvo/Char.h
arvo/Complex.h
arvo/form.h
arvo/Matrix.h
arvo/Perm.h
arvo/Rand.h
arvo/SI_units.h
arvo/SphTri.h
arvo/SVD.h
arvo/Token.h
arvo/Vec2.h
arvo/Vec3.h
arvo/Vec4.h
arvo/Vector.h
)
SET( SOURCES
avpcl.cpp
avpcl_mode0.cpp
avpcl_mode1.cpp
avpcl_mode2.cpp
avpcl_mode3.cpp
avpcl_mode4.cpp
avpcl_mode5.cpp
avpcl_mode6.cpp
avpcl_mode7.cpp
targa.cpp
utils.cpp
arvo/ArvoMath.cpp
arvo/Char.cpp
arvo/Complex.cpp
arvo/Matrix.cpp
arvo/Perm.cpp
arvo/Rand.cpp
arvo/SphTri.cpp
arvo/SVD.cpp
arvo/Token.cpp
arvo/Vec2.cpp
arvo/Vec3.cpp
arvo/Vec4.cpp
arvo/Vector.cpp
)
ADD_LIBRARY( avpcl
${HEADERS}
${SOURCES}
)

View file

@ -1,118 +0,0 @@
# Copyright 2016 The University of North Carolina at Chapel Hill
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Please send all BUG REPORTS to <pavel@cs.unc.edu>.
# <http://gamma.cs.unc.edu/FasTC/>
SET( SOURCES
"src/TexComp.cpp"
"src/CompressedImage.cpp"
)
SET( LIBRARY_HEADERS
"include/FasTC/CompressedImage.h"
"include/FasTC/ReferenceCounter.h"
"include/FasTC/StopWatch.h"
"include/FasTC/TexComp.h"
"include/FasTC/ThreadSafeStreambuf.h"
)
SET( HEADERS
${LIBRARY_HEADERS}
"src/CompressionFuncs.h"
)
# Make sure to add the appropriate stopwatch files...
IF( WIN32 )
SET( SOURCES ${SOURCES} "src/StopWatchWin32.cpp" )
ELSEIF( APPLE )
SET( SOURCES ${SOURCES} "src/StopWatchOSX.cpp" )
ELSE()
SET( SOURCES ${SOURCES} "src/StopWatchUnix.cpp" )
# Assume compiler is GCC
SET( LINK_FLAGS -lrt ${LINK_FLAGS} )
ENDIF()
###### Find Threads....
IF( MSVC )
SET( SOURCES ${SOURCES} "src/ThreadWin32.cpp" )
ELSE()
FIND_PACKAGE( Threads )
IF( CMAKE_USE_PTHREADS_INIT )
SET( SOURCES ${SOURCES} "src/ThreadPThread.cpp" )
ELSE()
MESSAGE( FATAL_ERROR "Could not find suitable threading library." )
ENDIF()
ENDIF()
# Add internal sources
SET( HEADERS ${HEADERS} "src/Thread.h" )
SET( HEADERS ${HEADERS} "src/ThreadGroup.h" )
SET( HEADERS ${HEADERS} "src/WorkerQueue.h" )
SET( SOURCES ${SOURCES} "src/ThreadSafeStreambuf.cpp" )
SET( SOURCES ${SOURCES} "src/Thread.cpp" )
SET( SOURCES ${SOURCES} "src/ThreadGroup.cpp" )
SET( SOURCES ${SOURCES} "src/WorkerQueue.cpp" )
# Dependencies...
INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/Base/include )
INCLUDE_DIRECTORIES( ${FasTC_BINARY_DIR}/Base/include )
INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/Core/include )
INCLUDE_DIRECTORIES( ${FasTC_BINARY_DIR}/Core/include )
INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/IO/include )
INCLUDE_DIRECTORIES( ${FasTC_BINARY_DIR}/IO/include )
INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/ASTCEncoder/include )
INCLUDE_DIRECTORIES( ${FasTC_BINARY_DIR}/ASTCEncoder/include )
INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/ETCEncoder/include )
INCLUDE_DIRECTORIES( ${FasTC_BINARY_DIR}/ETCEncoder/include )
INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/DXTEncoder/include )
INCLUDE_DIRECTORIES( ${FasTC_BINARY_DIR}/DXTEncoder/include )
INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/PVRTCEncoder/include)
INCLUDE_DIRECTORIES( ${FasTC_BINARY_DIR}/PVRTCEncoder/include)
INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/BPTCEncoder/include )
INCLUDE_DIRECTORIES( ${FasTC_BINARY_DIR}/BPTCEncoder/include )
ADD_LIBRARY( FasTCCore
${HEADERS}
${SOURCES}
)
INSTALL(
TARGETS FasTCCore
EXPORT FasTCTargets
ARCHIVE DESTINATION lib COMPONENT lib
)
INSTALL(
FILES ${LIBRARY_HEADERS}
DESTINATION ${INCLUDE_INSTALL_DIR}/FasTC COMPONENT dev)
TARGET_LINK_LIBRARIES( FasTCCore FasTCBase )
TARGET_LINK_LIBRARIES( FasTCCore FasTCIO )
TARGET_LINK_LIBRARIES( FasTCCore ETCEncoder )
TARGET_LINK_LIBRARIES( FasTCCore DXTEncoder )
TARGET_LINK_LIBRARIES( FasTCCore BPTCEncoder )
TARGET_LINK_LIBRARIES( FasTCCore PVRTCEncoder )
TARGET_LINK_LIBRARIES( FasTCCore ASTCEncoder )
IF( CMAKE_USE_PTHREADS_INIT )
TARGET_LINK_LIBRARIES( FasTCCore ${CMAKE_THREAD_LIBS_INIT} )
ENDIF()
IF( NOT WIN32 AND NOT APPLE )
TARGET_LINK_LIBRARIES( FasTCCore rt )
ENDIF()

View file

@ -1,74 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#ifndef _COMPRESSED_IMAGE_H_
#define _COMPRESSED_IMAGE_H_
#include "FasTC/TexCompTypes.h"
#include "FasTC/CompressionFormat.h"
#include "FasTC/Image.h"
class CompressedImage : public FasTC::Image<FasTC::Pixel> {
private:
FasTC::ECompressionFormat m_Format;
uint8 *m_CompressedData;
typedef FasTC::Image<FasTC::Pixel> UncompressedImage;
public:
CompressedImage(const CompressedImage &);
CompressedImage &operator=(const CompressedImage &);
// Create a compressed image from the given data according to
// the passed format. The size of the data is expected to conform
// to the width, height, and format specified.
CompressedImage(
const uint32 width,
const uint32 height,
const FasTC::ECompressionFormat format,
const uint8 *data
);
virtual ~CompressedImage();
virtual FasTC::Image<FasTC::Pixel> *Clone() const {
return new CompressedImage(*this);
}
virtual void ComputePixels();
static uint32 GetCompressedSize(uint32 width, uint32 height, FasTC::ECompressionFormat format);
uint32 GetCompressedSize() const {
return GetCompressedSize(GetWidth(), GetHeight(), m_Format);
}
uint32 GetUncompressedSize() const {
return GetWidth() * GetHeight() * sizeof(uint32);
}
// Decompress the compressed image data into outBuf. outBufSz is expected
// to be the proper size determined by the width, height, and format.
// !FIXME! We should have a function to explicitly return the in/out buf
// size for a given compressed image.
bool DecompressImage(uint8 *outBuf, uint32 outBufSz) const;
const uint8 *GetCompressedData() const { return m_CompressedData; }
FasTC::ECompressionFormat GetFormat() const { return m_Format; }
};
#endif // _COMPRESSED_IMAGE_H_

View file

@ -1,67 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#ifndef __REFERENCE_COUNTER_H__
#define __REFERENCE_COUNTER_H__
#include "TexCompTypes.h"
class ReferenceCounter {
public:
ReferenceCounter() : m_ReferenceCount( new uint32 ) {
*m_ReferenceCount = 1;
}
ReferenceCounter(const ReferenceCounter &other)
: m_ReferenceCount(other.m_ReferenceCount) {
IncRefCount();
}
ReferenceCounter &operator=(const ReferenceCounter &other) {
DecRefCount();
m_ReferenceCount = other.m_ReferenceCount;
IncRefCount();
return *this;
}
uint32 GetRefCount() const {
if(m_ReferenceCount)
return *m_ReferenceCount;
else
return 0;
}
void DecRefCount() {
if(!m_ReferenceCount) return;
(*m_ReferenceCount)--;
if(*m_ReferenceCount == 0) {
delete m_ReferenceCount;
m_ReferenceCount = 0;
}
}
void IncRefCount() {
if(!m_ReferenceCount) return;
(*m_ReferenceCount)++;
}
private:
uint32 *m_ReferenceCount;
};
#endif // __REFERENCE_COUNTER_H__

View file

@ -1,70 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
// The original lisence from the code available at the following location:
// http://software.intel.com/en-us/vcsource/samples/fast-texture-compression
//
// This code has been modified significantly from the original.
//--------------------------------------------------------------------------------------
// Copyright 2011 Intel Corporation
// All Rights Reserved
//
// Permission is granted to use, copy, distribute and prepare derivative works of this
// software for any purpose and without fee, provided, that the above copyright notice
// and this statement appear in all copies. Intel makes no representations about the
// suitability of this software for any purpose. THIS SOFTWARE IS PROVIDED "AS IS."
// INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, AND ALL LIABILITY,
// INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE,
// INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not
// assume any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
//
//--------------------------------------------------------------------------------------
#ifndef __TEXCOMP_STOP_WATCH_H__
#define __TEXCOMP_STOP_WATCH_H__
// Forward declare the private implementation of the class that will actually implement
// the timing features. This class is defined in each module depending on the platform...
class StopWatchImpl;
// A simple stopwatch class using Windows' high-resolution performance counters.
class StopWatch
{
public:
StopWatch();
StopWatch(const StopWatch &);
~StopWatch();
StopWatch &operator=(const StopWatch &);
void Start();
void Stop();
void Reset();
double TimeInSeconds() const;
double TimeInMilliseconds() const;
double TimeInMicroseconds() const;
private:
StopWatchImpl *impl;
};
#endif // __TEXCOMP_STOP_WATCH_H__

View file

@ -1,98 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#ifndef _TEX_COMP_H_
#define _TEX_COMP_H_
#include "FasTC/CompressedImage.h"
#include "FasTC/CompressionJob.h"
#include <iosfwd>
#include "FasTC/ImageFwd.h"
// Forward declarations
class ImageFile;
struct SCompressionSettings {
SCompressionSettings(); // defaults
// The compression format for the image.
FasTC::ECompressionFormat format;
// The flag that requests us to use SIMD, if it is available
bool bUseSIMD;
// The number of threads to spawn in order to process the data
int iNumThreads;
// Some compression formats take a measurement of quality when
// compressing an image. If the format supports it, this value
// will be used for quality purposes.
int iQuality;
// The number of compressions to perform. The program will compress
// the image this many times, and then take the average of the timing.
int iNumCompressions;
// This setting measures the number of blocks that a thread
// will process at any given time. If this value is zero,
// which is the default, the work will be divided by the
// number of threads, and each thread will do it's job and
// exit.
int iJobSize;
// This flags instructs the compression routine to be launched in succession
// with many threads at once. Atomic expressions based on the availability
// in the platform and compiler will provide synchronization.
bool bUseAtomics;
// This flag instructs the infrastructure to use the compression routine from
// PVRTexLib. If no such lib is found during configuration then this flag is
// ignored. The quality being used is the fastest compression quality.
bool bUsePVRTexLib;
// This flag instructs the infrastructure to use the compression routine from
// NVidia Texture Tools. If no such lib is found during configuration then this
// flag is ignored.
bool bUseNVTT;
// This is the output stream with which we should output the logs for the
// compression functions.
std::ostream *logStream;
};
template<typename PixelType>
extern CompressedImage *CompressImage(FasTC::Image<PixelType> *img, const SCompressionSettings &settings);
extern bool CompressImageData(
const unsigned char *data,
const unsigned int width,
const unsigned int height,
unsigned char *cmpData,
const unsigned int cmpDataSz,
const SCompressionSettings &settings
);
// This function computes the Peak Signal to Noise Ratio between a
// compressed image and a raw image.
extern double ComputePSNR(const CompressedImage &ci, const ImageFile &file);
// This is a multi-platform yield function that preempts the current thread
// based on the threading library that we're using.
extern void YieldThread();
#endif //_TEX_COMP_H_

View file

@ -1,42 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#ifndef CORE_INCLUDE_THREADSAFESTREAMBUF_H_
#define CORE_INCLUDE_THREADSAFESTREAMBUF_H_
// Forward Declarations
class TCMutex;
#include <streambuf>
#include <iosfwd>
class ThreadSafeStreambuf : public ::std::streambuf {
public:
ThreadSafeStreambuf(std::ostream &sink);
virtual ~ThreadSafeStreambuf();
protected:
virtual std::streamsize xsputn(const char_type *s, std::streamsize count);
private:
// Not implemented -- not allowed...
ThreadSafeStreambuf(const ThreadSafeStreambuf &);
ThreadSafeStreambuf &operator=(const ThreadSafeStreambuf &);
std::ostream &m_Sink;
TCMutex *m_Mutex;
};
#endif // CORE_INCLUDE_THREADSAFESTREAMBUF_H_

View file

@ -1,149 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "FasTC/CompressedImage.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "FasTC/Pixel.h"
#include "FasTC/TexCompTypes.h"
#include "FasTC/BPTCCompressor.h"
#include "FasTC/PVRTCCompressor.h"
#include "FasTC/DXTCompressor.h"
#include "FasTC/ETCCompressor.h"
#include "FasTC/ASTCCompressor.h"
using FasTC::CompressionJob;
using FasTC::DecompressionJob;
using FasTC::ECompressionFormat;
CompressedImage::CompressedImage( const CompressedImage &other )
: UncompressedImage(other)
, m_Format(other.m_Format)
, m_CompressedData(0)
{
if(other.m_CompressedData) {
uint32 compressedSz = GetCompressedSize();
m_CompressedData = new uint8[compressedSz];
memcpy(m_CompressedData, other.m_CompressedData, compressedSz);
}
}
CompressedImage::CompressedImage(
const unsigned int width,
const unsigned int height,
const ECompressionFormat format,
const unsigned char *data
)
: UncompressedImage(width, height, reinterpret_cast<uint32 *>(NULL))
, m_Format(format)
, m_CompressedData(0)
{
uint32 cmpSz = GetCompressedSize();
if(cmpSz > 0) {
assert(!m_CompressedData);
m_CompressedData = new uint8[cmpSz];
memcpy(m_CompressedData, data, cmpSz);
}
}
CompressedImage &CompressedImage::operator=(const CompressedImage &other) {
UncompressedImage::operator=(other);
m_Format = other.m_Format;
if(other.m_CompressedData) {
uint32 cmpSz = GetCompressedSize();
m_CompressedData = new uint8[cmpSz];
memcpy(m_CompressedData, other.m_CompressedData, cmpSz);
}
return *this;
}
CompressedImage::~CompressedImage() {
if(m_CompressedData) {
delete m_CompressedData;
m_CompressedData = NULL;
}
}
bool CompressedImage::DecompressImage(unsigned char *outBuf, unsigned int outBufSz) const {
assert(outBufSz == GetUncompressedSize());
uint8 *byteData = reinterpret_cast<uint8 *>(m_CompressedData);
DecompressionJob dj (m_Format, byteData, outBuf, GetWidth(), GetHeight());
if(m_Format == FasTC::eCompressionFormat_DXT1) {
DXTC::DecompressDXT1(dj);
} else if(m_Format == FasTC::eCompressionFormat_DXT5) {
DXTC::DecompressDXT5(dj);
} else if (m_Format == FasTC::eCompressionFormat_ETC1) {
ETCC::Decompress(dj);
} else if(FasTC::COMPRESSION_FORMAT_PVRTC_BEGIN <= m_Format &&
FasTC::COMPRESSION_FORMAT_PVRTC_END >= m_Format) {
#ifndef NDEBUG
PVRTCC::Decompress(dj, PVRTCC::eWrapMode_Wrap, true);
#else
PVRTCC::Decompress(dj);
#endif
} else if(m_Format == FasTC::eCompressionFormat_BPTC) {
BPTCC::Decompress(dj);
} else if(FasTC::COMPRESSION_FORMAT_ASTC_BEGIN <= m_Format &&
FasTC::COMPRESSION_FORMAT_ASTC_END >= m_Format) {
ASTCC::Decompress(dj);
} else {
const char *errStr = "Have not implemented decompression method.";
fprintf(stderr, "%s\n", errStr);
assert(!errStr);
return false;
}
return true;
}
void CompressedImage::ComputePixels() {
uint32 unCompSz = GetWidth() * GetHeight() * 4;
uint8 *unCompBuf = new uint8[unCompSz];
DecompressImage(unCompBuf, unCompSz);
uint32 * newPixelBuf = reinterpret_cast<uint32 *>(unCompBuf);
FasTC::Pixel *newPixels = new FasTC::Pixel[GetWidth() * GetHeight()];
for(uint32 i = 0; i < GetWidth() * GetHeight(); i++) {
newPixels[i].Unpack(newPixelBuf[i]);
}
SetImageData(GetWidth(), GetHeight(), newPixels);
}
uint32 CompressedImage::GetCompressedSize(uint32 width, uint32 height, ECompressionFormat format) {
// The compressed size is the block size times the number of blocks
uint32 blockDim[2];
GetBlockDimensions(format, blockDim);
const uint32 blocksWide = (width + blockDim[0] - 1) / blockDim[0];
const uint32 blocksHigh = (height + blockDim[1] - 1) / blockDim[1];
const uint32 uncompBlockSize = blockDim[0] * blockDim[1] * sizeof(uint32);
const uint32 nBlocks = blocksWide * blocksHigh;
const uint32 blockSz = GetBlockSize(format);
return nBlocks * blockSz;
}

View file

@ -1,36 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#ifndef CORE_SRC_COMPRESSIONFUNCS_H_
#define CORE_SRC_COMPRESSIONFUNCS_H_
#include "FasTC/CompressionJob.h"
#include <iosfwd>
// A compression function format. It takes the raw data and image dimensions and
// returns the compressed image data into outData. It is assumed that there is
// enough space allocated for outData to store the compressed data. Allocation
// is dependent on the compression format.
typedef void (* CompressionFunc)(const FasTC::CompressionJob &);
// A compression function format. It takes the raw data and image dimensions and
// returns the compressed image data into outData. It is assumed that there is
// enough space allocated for outData to store the compressed data. Allocation
// is dependent on the compression format.
typedef void (* CompressionFuncWithStats)(const FasTC::CompressionJob &, std::ostream *logStream);
#endif // CORE_SRC_COMPRESSIONFUNCS_H_

View file

@ -1,81 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "FasTC/StopWatch.h"
#include "FasTC/TexCompTypes.h"
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
class StopWatchImpl {
public:
uint64 start;
uint64 duration;
};
static uint64 Now() {
timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_usec + (1e6 * tv.tv_sec);
}
StopWatch::StopWatch(const StopWatch &other) {
impl = new StopWatchImpl();
memcpy(impl, other.impl, sizeof(StopWatchImpl));
}
StopWatch &StopWatch::operator=(const StopWatch &other) {
if(impl) {
delete impl;
}
impl = new StopWatchImpl();
memcpy(impl, other.impl, sizeof(StopWatchImpl));
return *this;
}
StopWatch::~StopWatch() {
delete impl;
}
StopWatch::StopWatch() : impl(new StopWatchImpl) {
Reset();
}
void StopWatch::Start() {
impl->start = Now();
}
void StopWatch::Stop() {
impl->duration = Now() - impl->start;
}
void StopWatch::Reset() {
impl->start = impl->duration = 0.0;
}
double StopWatch::TimeInSeconds() const {
return double(impl->duration) / 1e6;
}
double StopWatch::TimeInMilliseconds() const {
return double(impl->duration) / 1e3;
}
double StopWatch::TimeInMicroseconds() const {
return double(impl->duration);
}

View file

@ -1,80 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "FasTC/StopWatch.h"
#include "FasTC/TexCompTypes.h"
#include <stdlib.h>
#include <string.h>
#include <time.h>
class StopWatchImpl {
public:
timespec ts;
double timer;
double duration;
};
StopWatch::StopWatch(const StopWatch &other) {
impl = new StopWatchImpl();
memcpy(impl, other.impl, sizeof(StopWatchImpl));
}
StopWatch &StopWatch::operator=(const StopWatch &other) {
if(impl) {
delete impl;
}
impl = new StopWatchImpl();
memcpy(impl, other.impl, sizeof(StopWatchImpl));
return *this;
}
StopWatch::~StopWatch() {
delete impl;
}
StopWatch::StopWatch() : impl(new StopWatchImpl) {
Reset();
}
void StopWatch::Start() {
clock_gettime(CLOCK_REALTIME, &(impl->ts));
impl->timer = double(impl->ts.tv_sec) + 1e-9 * double(impl->ts.tv_nsec);
}
void StopWatch::Stop() {
clock_gettime(CLOCK_REALTIME, &(impl->ts));
impl->duration = -(impl->timer) + (double(impl->ts.tv_sec) + 1e-9 * double(impl->ts.tv_nsec));
}
void StopWatch::Reset() {
impl->timer = impl->duration = 0.0;
memset(&(impl->ts), 0, sizeof(timespec));
}
double StopWatch::TimeInSeconds() const {
return impl->duration;
}
double StopWatch::TimeInMilliseconds() const {
return impl->duration * 1000;
}
double StopWatch::TimeInMicroseconds() const {
return impl->duration * 1000000;
}

View file

@ -1,180 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
// The original lisence from the code available at the following location:
// http://software.intel.com/en-us/vcsource/samples/fast-texture-compression
//
// This code has been modified significantly from the original.
//--------------------------------------------------------------------------------------
// Copyright 2011 Intel Corporation
// All Rights Reserved
//
// Permission is granted to use, copy, distribute and prepare derivative works of this
// software for any purpose and without fee, provided, that the above copyright notice
// and this statement appear in all copies. Intel makes no representations about the
// suitability of this software for any purpose. THIS SOFTWARE IS PROVIDED "AS IS."
// INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, AND ALL LIABILITY,
// INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE,
// INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not
// assume any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
//
//--------------------------------------------------------------------------------------
#include "FasTC/StopWatch.h"
#include "FasTC/TexCompTypes.h"
#include <cassert>
#include <Windows.h>
#include <WinBase.h>
class StopWatchImpl {
public:
uint64 frequency;
uint64 start;
uint64 stop;
#ifndef __MINGW32__
uintptr_t affinityMask;
#endif
StopWatchImpl() :
start(0), stop(0)
#ifndef __MINGW32__
, affinityMask(0)
#endif
{
// Initialize the performance counter frequency.
LARGE_INTEGER perfQuery;
#ifndef NDEBUG
assert(QueryPerformanceFrequency(&perfQuery));
#else
QueryPerformanceFrequency(&perfQuery);
#endif
this->frequency = perfQuery.QuadPart;
}
};
StopWatch::StopWatch() : impl(new StopWatchImpl) { }
StopWatch::StopWatch(const StopWatch &other) {
impl = new StopWatchImpl();
memcpy(impl, other.impl, sizeof(StopWatchImpl));
}
StopWatch &StopWatch::operator=(const StopWatch &other) {
if(impl) {
delete impl;
}
impl = new StopWatchImpl();
memcpy(impl, other.impl, sizeof(StopWatchImpl));
return *this;
}
StopWatch::~StopWatch() {
delete impl;
}
// Start the stopwatch.
void StopWatch::Start()
{
#ifndef __MINGW32__
// MSDN recommends setting the thread affinity to avoid bugs in the BIOS and HAL.
// Create an affinity mask for the current processor.
impl->affinityMask = (DWORD_PTR)1 << GetCurrentProcessorNumber();
HANDLE currThread = GetCurrentThread();
DWORD_PTR prevAffinityMask = SetThreadAffinityMask(currThread, impl->affinityMask);
assert(prevAffinityMask != 0);
#endif
// Query the performance counter.
LARGE_INTEGER perfQuery;
#ifndef NDEBUG
assert(QueryPerformanceCounter(&perfQuery));
#else
QueryPerformanceCounter(&perfQuery);
#endif
impl->start = perfQuery.QuadPart;
#ifndef __MINGW32__
// Restore the thread's affinity mask.
prevAffinityMask = SetThreadAffinityMask(currThread, prevAffinityMask);
assert(prevAffinityMask != 0);
#endif
}
// Stop the stopwatch.
void StopWatch::Stop()
{
#ifndef __MINGW32__
// MSDN recommends setting the thread affinity to avoid bugs in the BIOS and HAL.
// Use the affinity mask that was created in the Start function.
HANDLE currThread = GetCurrentThread();
DWORD_PTR prevAffinityMask = SetThreadAffinityMask(currThread, impl->affinityMask);
assert(prevAffinityMask != 0);
#endif
// Query the performance counter.
LARGE_INTEGER perfQuery;
#ifndef NDEBUG
assert(QueryPerformanceCounter(&perfQuery));
#else
QueryPerformanceCounter(&perfQuery);
#endif
impl->stop = perfQuery.QuadPart;
#ifndef __MINGW32__
// Restore the thread's affinity mask.
prevAffinityMask = SetThreadAffinityMask(currThread, prevAffinityMask);
assert(prevAffinityMask != 0);
#endif
}
// Reset the stopwatch.
void StopWatch::Reset()
{
impl->start = 0;
impl->stop = 0;
#ifndef __MINGW32__
impl->affinityMask = 0;
#endif
}
// Get the elapsed time in seconds.
double StopWatch::TimeInSeconds() const
{
// Return the elapsed time in seconds.
assert((impl->stop - impl->start) > 0);
return double(impl->stop - impl->start) / double(impl->frequency);
}
// Get the elapsed time in milliseconds.
double StopWatch::TimeInMilliseconds() const
{
// Return the elapsed time in milliseconds.
assert((impl->stop - impl->start) > 0);
return double(impl->stop - impl->start) / double(impl->frequency) * 1000.0;
}
// Get the elapsed time in microseconds.
double StopWatch::TimeInMicroseconds() const
{
// Return the elapsed time in microseconds.
assert((impl->stop - impl->start) > 0);
return double(impl->stop - impl->start) / double(impl->frequency) * 1000000.0;
}

View file

@ -1,529 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "FasTC/TexComp.h"
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cassert>
#include <iostream>
#include <string.h>
#include "FasTC/BPTCCompressor.h"
#include "FasTC/CompressionFormat.h"
#include "FasTC/DXTCompressor.h"
#include "FasTC/ETCCompressor.h"
#include "FasTC/ImageFile.h"
#include "FasTC/Pixel.h"
#include "FasTC/PVRTCCompressor.h"
#include "CompressionFuncs.h"
#include "Thread.h"
#include "ThreadGroup.h"
#include "WorkerQueue.h"
using FasTC::CompressionJob;
using FasTC::CompressionJobList;
using FasTC::ECompressionFormat;
template <typename T>
static void clamp(T &x, const T &minX, const T &maxX) {
x = std::max(std::min(maxX, x), minX);
}
template <typename T>
static inline T sad(const T &a, const T &b) {
return (a > b)? a - b : b - a;
}
static BPTCC::CompressionSettings gBPTCSettings;
static void CompressBPTC(const CompressionJob &cj) {
BPTCC::Compress(cj, gBPTCSettings);
}
static void CompressBPTCWithStats(const CompressionJob &cj,
std::ostream *strm) {
BPTCC::CompressWithStats(cj, strm, gBPTCSettings);
}
static void CompressPVRTC(const CompressionJob &cj) {
PVRTCC::Compress(cj);
}
static void CompressPVRTCLib(const CompressionJob &cj) {
#ifdef PVRTEXLIB_FOUND
PVRTCC::CompressPVRLib(cj);
#else
fprintf(stderr, "WARNING: PVRTexLib not found, defaulting to FasTC implementation.\n");
PVRTCC::Compress(cj);
#endif
}
SCompressionSettings:: SCompressionSettings()
: format(FasTC::eCompressionFormat_BPTC)
, bUseSIMD(false)
, iNumThreads(1)
, iQuality(50)
, iNumCompressions(1)
{
clamp(iQuality, 0, 256);
}
static CompressionFuncWithStats ChooseFuncFromSettingsWithStats(const SCompressionSettings &s) {
switch(s.format) {
case FasTC::eCompressionFormat_BPTC:
{
#ifdef FOUND_NVTT_BPTC_EXPORT
if(s.bUseNVTT)
return BPTCC::CompressNVTTWithStats;
else
#endif
return CompressBPTCWithStats;
}
break;
default:
{
assert(!"Not implemented!");
return NULL;
}
}
return NULL;
}
static CompressionFunc ChooseFuncFromSettings(const SCompressionSettings &s) {
switch(s.format) {
case FasTC::eCompressionFormat_BPTC:
{
gBPTCSettings.m_NumSimulatedAnnealingSteps = s.iQuality;
#ifdef HAS_SSE_41
if(s.bUseSIMD) {
return BPTCC::CompressImageBPTCSIMD;
}
#endif
#ifdef FOUND_NVTT_BPTC_EXPORT
if(s.bUseNVTT)
return BPTCC::CompressNVTT;
else
#endif
return CompressBPTC;
}
break;
case FasTC::eCompressionFormat_DXT1:
return DXTC::CompressImageDXT1;
case FasTC::eCompressionFormat_DXT5:
return DXTC::CompressImageDXT5;
case FasTC::eCompressionFormat_PVRTC4:
{
if(s.bUsePVRTexLib) {
return CompressPVRTCLib;
} else {
return CompressPVRTC;
}
}
case FasTC::eCompressionFormat_ETC1:
return ETCC::Compress_RG;
default:
{
assert(!"Not implemented!");
return NULL;
}
}
return NULL;
}
static void ReportError(const char *msg) {
fprintf(stderr, "TexComp -- %s\n", msg);
}
static double CompressImageInSerial(
const CompressionJob &job,
const SCompressionSettings &settings
) {
CompressionFunc f = ChooseFuncFromSettings(settings);
CompressionFuncWithStats fStats = NULL;
if (settings.logStream) {
fStats = ChooseFuncFromSettingsWithStats(settings);
}
double cmpTimeTotal = 0.0;
StopWatch stopWatch = StopWatch();
for(int i = 0; i < settings.iNumCompressions; i++) {
stopWatch.Reset();
stopWatch.Start();
if(fStats && settings.logStream) {
(*fStats)(job, settings.logStream);
} else {
(*f)(job);
}
stopWatch.Stop();
cmpTimeTotal += stopWatch.TimeInMilliseconds();
}
double cmpTime = cmpTimeTotal / double(settings.iNumCompressions);
return cmpTime;
}
#ifdef HAS_ATOMICS
class AtomicThreadUnit : public TCCallable {
CompressionJobList &m_CompressionJobList;
TCBarrier *m_Barrier;
CompressionFunc m_CmpFnc;
public:
AtomicThreadUnit(
CompressionJobList &_cjl,
TCBarrier *barrier,
CompressionFunc f
) : TCCallable(),
m_CompressionJobList(_cjl),
m_Barrier(barrier),
m_CmpFnc(f)
{ }
virtual ~AtomicThreadUnit() { }
virtual void operator()() {
m_Barrier->Wait();
if(m_CmpFnc == CompressBPTC) {
BPTCC::CompressAtomic(m_CompressionJobList);
}
else {
assert(!"I don't know what we're compressing...");
}
}
};
static double CompressImageWithAtomics(
const CompressionJob &cj,
const SCompressionSettings &settings
) {
CompressionFunc f = ChooseFuncFromSettings(settings);
// Setup compression list...
const int nTimes = settings.iNumCompressions;
CompressionJobList cjl (nTimes);
for(int i = 0; i < nTimes; i++) {
if(!cjl.AddJob(cj)) {
assert(!"Error adding compression job to job list!");
}
}
const int nThreads = settings.iNumThreads;
// Allocate resources...
TCBarrier barrier (nThreads+1);
TCThread **threads = (TCThread **)malloc(nThreads * sizeof(TCThread *));
AtomicThreadUnit **units = (AtomicThreadUnit **)malloc(nThreads * sizeof(AtomicThreadUnit *));
// Launch threads...
for(int i = 0; i < nThreads; i++) {
AtomicThreadUnit *u = new AtomicThreadUnit(cjl, &barrier, f);
threads[i] = new TCThread(*u);
units[i] = u;
}
// Wait here to make sure that our timer is correct...
barrier.Wait();
StopWatch sw;
sw.Start();
// Wait for threads to finish
for(int i = 0; i < nThreads; i++) {
threads[i]->Join();
}
sw.Stop();
// Cleanup
for(int i = 0; i < nThreads; i++)
delete threads[i];
free(threads);
for(int i = 0; i < nThreads; i++)
delete units[i];
free(units);
// Compression time
double cmpTimeTotal = sw.TimeInMilliseconds();
return cmpTimeTotal / double(settings.iNumCompressions);
}
#else // HAS_ATOMICS
static double CompressImageWithAtomics(
const CompressionJob &cj,
const SCompressionSettings &settings
) {
fprintf(stderr, "Compiler does not support atomic operations!");
}
#endif
static double CompressThreadGroup(ThreadGroup &tgrp, const SCompressionSettings &settings) {
if(!(tgrp.PrepareThreads())) {
assert(!"Thread group failed to prepare threads?!");
return -1.0f;
}
double cmpTimeTotal = 0.0;
for(int i = 0; i < settings.iNumCompressions; i++) {
if(i > 0)
tgrp.PrepareThreads();
tgrp.Start();
tgrp.Join();
StopWatch stopWatch = tgrp.GetStopWatch();
cmpTimeTotal += tgrp.GetStopWatch().TimeInMilliseconds();
}
tgrp.CleanUpThreads();
return cmpTimeTotal;
}
static double CompressImageWithThreads(
const CompressionJob &job,
const SCompressionSettings &settings
) {
CompressionFunc f = ChooseFuncFromSettings(settings);
CompressionFuncWithStats fStats = ChooseFuncFromSettingsWithStats(settings);
double cmpTimeTotal = 0.0;
if(fStats && settings.logStream) {
ThreadGroup tgrp (settings.iNumThreads, job, fStats, settings.logStream);
cmpTimeTotal = CompressThreadGroup(tgrp, settings);
}
else {
ThreadGroup tgrp (settings.iNumThreads, job, f);
cmpTimeTotal = CompressThreadGroup(tgrp, settings);
}
double cmpTime = cmpTimeTotal / double(settings.iNumCompressions);
return cmpTime;
}
static double RunWorkerQueue(WorkerQueue &wq) {
wq.Run();
return wq.GetStopWatch().TimeInMilliseconds();
}
static double CompressImageWithWorkerQueue(
const CompressionJob &job,
const SCompressionSettings &settings
) {
CompressionFunc f = ChooseFuncFromSettings(settings);
CompressionFuncWithStats fStats = ChooseFuncFromSettingsWithStats(settings);
double cmpTimeTotal = 0.0;
if(fStats && settings.logStream) {
WorkerQueue wq (
settings.iNumCompressions,
settings.iNumThreads,
settings.iJobSize,
job,
fStats,
settings.logStream
);
cmpTimeTotal = RunWorkerQueue(wq);
}
else {
WorkerQueue wq (
settings.iNumCompressions,
settings.iNumThreads,
settings.iJobSize,
job,
f
);
cmpTimeTotal = RunWorkerQueue(wq);
}
return cmpTimeTotal / double(settings.iNumCompressions);
}
template<typename PixelType>
CompressedImage *CompressImage(
FasTC::Image<PixelType> *img, const SCompressionSettings &settings
) {
if(!img) return NULL;
uint32 width = img->GetWidth();
uint32 height = img->GetHeight();
assert(width > 0);
assert(height > 0);
// Make sure that the width and height of the image is a multiple of
// the block size of the format
uint32 blockDims[2];
FasTC::GetBlockDimensions(settings.format, blockDims);
if ((width % blockDims[0]) != 0 || (height % blockDims[1]) != 0) {
ReportError("WARNING - Image size is not a multiple of block size. Padding with zeros...");
uint32 newWidth = ((width + (blockDims[0] - 1)) / blockDims[0]) * blockDims[0];
uint32 newHeight = ((height + (blockDims[1] - 1)) / blockDims[1]) * blockDims[1];
assert(newWidth > width || newHeight > height);
assert(newWidth % blockDims[0] == 0);
assert(newHeight % blockDims[1] == 0);
width = newWidth;
height = newHeight;
}
uint32 *data = new uint32[width * height];
memset(data, 0, width * height * sizeof(data[0]));
CompressedImage *outImg = NULL;
// Allocate data based on the compression method
uint32 cmpDataSz = CompressedImage::GetCompressedSize(width, height, settings.format);
// Make sure that we have RGBA data...
img->ComputePixels();
for(uint32 j = 0; j < img->GetHeight(); j++) {
for(uint32 i = 0; i < img->GetWidth(); i++) {
data[j * width + i] = (*img)(i, j).Pack();
}
}
unsigned char *cmpData = new unsigned char[cmpDataSz];
uint8 *dataPtr = reinterpret_cast<uint8 *>(data);
if (CompressImageData(dataPtr, width, height, cmpData, cmpDataSz, settings)) {
outImg = new CompressedImage(width, height, settings.format, cmpData);
}
delete [] data;
delete [] cmpData;
return outImg;
}
// !FIXME! Ideally, we wouldn't have to do this because there would be a way to instantiate this
// function in the header or using some fancy template metaprogramming. I can't think of the way
// at the moment.
template CompressedImage *CompressImage(FasTC::Image<FasTC::Pixel> *, const SCompressionSettings &settings);
bool CompressImageData(
const uint8 *data,
const uint32 width,
const uint32 height,
uint8 *compressedData,
const uint32 cmpDataSz,
const SCompressionSettings &settings
) {
uint32 dataSz = width * height * 4;
// Make sure that platform supports SSE if they chose this
// option...
#ifndef HAS_SSE_41
if(settings.bUseSIMD) {
ReportError("Platform does not support SIMD!\n");
return false;
}
#endif
#ifndef HAS_ATOMICS
if(settings.bUseAtomics) {
ReportError("Compiler's atomic operations are not supported!\n");
return false;
}
#endif
if(dataSz <= 0) {
ReportError("No data sent to compress!");
return false;
}
uint32 numThreads = settings.iNumThreads;
if(settings.format == FasTC::eCompressionFormat_PVRTC4 &&
(settings.iNumThreads > 1 || settings.logStream)) {
if(settings.iNumThreads > 1) {
ReportError("WARNING - PVRTC compressor does not support multithreading.");
numThreads = 1;
}
if(settings.logStream) {
ReportError("WARNING - PVRTC compressor does not support stat collection.");
}
}
uint32 blockDims[2];
FasTC::GetBlockDimensions(settings.format, blockDims);
if ((width % blockDims[0]) != 0 || (height % blockDims[1]) != 0) {
ReportError("ERROR - CompressImageData: width or height is not multiple of block dimension");
return false;
} else if (settings.format == FasTC::eCompressionFormat_PVRTC4 &&
((width & (width - 1)) != 0 ||
(height & (height - 1)) != 0 ||
width != height)) {
ReportError("ERROR - CompressImageData: PVRTC4 images must be square and power-of-two.");
return false;
}
// Allocate data based on the compression method
uint32 compressedDataSzNeeded =
CompressedImage::GetCompressedSize(width, height, settings.format);
if(compressedDataSzNeeded == 0) {
ReportError("Unknown compression format");
return false;
}
else if(compressedDataSzNeeded > cmpDataSz) {
ReportError("Not enough space for compressed data!");
return false;
}
if(ChooseFuncFromSettings(settings)) {
CompressionJob cj(settings.format, data, compressedData, width, height);
double cmpMSTime = 0.0;
if(numThreads > 1) {
if(settings.bUseAtomics) {
cmpMSTime = CompressImageWithAtomics(cj, settings);
} else if(settings.iJobSize > 0) {
cmpMSTime = CompressImageWithWorkerQueue(cj, settings);
} else {
cmpMSTime = CompressImageWithThreads(cj, settings);
}
}
else {
cmpMSTime = CompressImageInSerial(cj, settings);
}
// Report compression time
fprintf(stdout, "Compression time: %0.3f ms\n", cmpMSTime);
}
else {
ReportError("Could not find adequate compression function for specified settings");
return false;
}
return true;
}
void YieldThread() {
TCThread::Yield();
}

View file

@ -1,138 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "Thread.h"
#include <assert.h>
////////////////////////////////////////////////////////////////////////////////
//
// Base Implementation
//
////////////////////////////////////////////////////////////////////////////////
TCThreadBase::TCThreadBase(const TCThreadBaseImplFactory &factory)
: m_Impl(factory.CreateImpl())
{ }
TCThreadBase::TCThreadBase(const TCThreadBase &other)
: m_Impl(other.m_Impl)
{
assert(m_Impl->GetReferenceCount() > 0);
m_Impl->IncreaseReferenceCount();
}
TCThreadBase &TCThreadBase::operator=(const TCThreadBase &other) {
assert(m_Impl->GetReferenceCount() > 0);
// We are no longer referencing this implementation...
m_Impl->DecreaseReferenceCount();
// If we're the last ones to reference it, then it should be destroyed.
if(m_Impl->GetReferenceCount() <= 0) {
delete m_Impl;
m_Impl = 0;
}
// Our implementation is now the same as the other.
m_Impl = other.m_Impl;
m_Impl->IncreaseReferenceCount();
return *this;
}
TCThreadBase::~TCThreadBase() {
// We are no longer referencing 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;
}
}
#ifndef NDEBUG
void TCThreadBase::CheckReferenceCount() {
assert(m_Impl->GetReferenceCount() > 0);
}
#endif
////////////////////////////////////////////////////////////////////////////////
//
// Barrier Implementation
//
////////////////////////////////////////////////////////////////////////////////
class TCBarrierImpl : public TCThreadBaseImpl {
private:
unsigned int m_ThreadLimit;
unsigned int m_ThreadCount;
unsigned int m_Times;
TCMutex m_Mutex;
TCConditionVariable m_CV;
public:
TCBarrierImpl(int threads)
: TCThreadBaseImpl()
, m_ThreadLimit(threads)
, m_ThreadCount(threads)
, m_Times(0)
{
assert(threads > 0);
}
virtual ~TCBarrierImpl() { }
bool Wait() {
TCLock lock(m_Mutex);
unsigned int times = m_Times;
if(--m_ThreadCount == 0) {
m_Times++;
m_ThreadCount = m_ThreadLimit;
m_CV.NotifyAll();
return true;
}
while(times == m_Times) {
m_CV.Wait(lock);
}
return false;
}
};
class TCBarrierImplFactory : public TCThreadBaseImplFactory {
private:
int m_NumThreads;
public:
TCBarrierImplFactory(int threads) : TCThreadBaseImplFactory(), m_NumThreads(threads) { }
virtual ~TCBarrierImplFactory() { }
virtual TCThreadBaseImpl *CreateImpl() const {
return new TCBarrierImpl(m_NumThreads);
}
};
TCBarrier::TCBarrier(int threads)
: TCThreadBase(TCBarrierImplFactory(threads))
{ }
void TCBarrier::Wait() {
((TCBarrierImpl *)m_Impl)->Wait();
}

View file

@ -1,149 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#ifndef __TEX_COMP_THREAD_H__
#define __TEX_COMP_THREAD_H__
#include "FasTC/TexCompTypes.h"
//!HACK! Apparently MSVC has issues with Yield()...????
#ifdef _MSC_VER
#undef Yield
#endif
////////////////////////////////////////////////////////////////////////////////
//
// Base implementation
//
////////////////////////////////////////////////////////////////////////////////
class TCThreadBaseImpl {
friend class TCThreadBase;
private:
int m_ReferenceCount;
void IncreaseReferenceCount() { m_ReferenceCount++; }
void DecreaseReferenceCount() { m_ReferenceCount--; }
int GetReferenceCount() const { return m_ReferenceCount; }
protected:
TCThreadBaseImpl()
: m_ReferenceCount(1)
{ }
virtual ~TCThreadBaseImpl() { }
};
class TCThreadBaseImplFactory {
protected:
TCThreadBaseImplFactory() { }
virtual ~TCThreadBaseImplFactory() { }
public:
virtual TCThreadBaseImpl *CreateImpl() const = 0;
};
class TCThreadBase {
protected:
TCThreadBase(const TCThreadBaseImplFactory &);
TCThreadBase(const TCThreadBase &);
TCThreadBase &operator=(const TCThreadBase &);
~TCThreadBase();
TCThreadBaseImpl *m_Impl;
#ifndef NDEBUG
void CheckReferenceCount();
#else
void CheckReferenceCount() { }
#endif
};
////////////////////////////////////////////////////////////////////////////////
//
// Thread implementation
//
////////////////////////////////////////////////////////////////////////////////
// The base class for a thread implementation
class TCCallable {
protected:
TCCallable() { }
public:
virtual ~TCCallable() { }
virtual void operator()() = 0;
};
class TCThread : public TCThreadBase {
public:
TCThread(TCCallable &);
static void Yield();
static uint64 ThreadID();
void Join();
};
////////////////////////////////////////////////////////////////////////////////
//
// Mutex implementation
//
////////////////////////////////////////////////////////////////////////////////
class TCMutex : public TCThreadBase {
friend class TCLockImpl;
public:
TCMutex();
};
////////////////////////////////////////////////////////////////////////////////
//
// Lock implementation
//
////////////////////////////////////////////////////////////////////////////////
class TCLock : public TCThreadBase {
friend class TCConditionVariableImpl;
public:
TCLock(TCMutex &);
};
////////////////////////////////////////////////////////////////////////////////
//
// Condition Variable implementation
//
////////////////////////////////////////////////////////////////////////////////
class TCConditionVariable : public TCThreadBase {
public:
TCConditionVariable();
void Wait(TCLock &);
void NotifyOne();
void NotifyAll();
};
////////////////////////////////////////////////////////////////////////////////
//
// Barrier implementation
//
////////////////////////////////////////////////////////////////////////////////
class TCBarrier : public TCThreadBase {
public:
TCBarrier(int threads);
void Wait();
};
#endif //__TEX_COMP_THREAD_H__

View file

@ -1,253 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "ThreadGroup.h"
#include "FasTC/BPTCCompressor.h"
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <iostream>
using FasTC::CompressionJob;
CmpThread::CmpThread()
: m_ParentCounter(NULL)
, m_StartBarrier(NULL)
, m_ParentCounterLock(NULL)
, m_FinishCV(NULL)
, m_ParentExitFlag(NULL)
, m_Job(CompressionJob(FasTC::kNumCompressionFormats, NULL, NULL, 0, 0))
, m_CmpFunc(NULL)
, m_CmpFuncWithStats(NULL)
, m_LogStream(NULL)
{ }
void CmpThread::operator()() {
if(!m_Job.OutBuf() || !m_Job.InBuf()
|| !m_ParentCounter || !m_ParentCounterLock || !m_FinishCV
|| !m_StartBarrier
|| !m_ParentExitFlag
) {
fprintf(stderr, "Incorrect thread initialization.\n");
return;
}
if(!(m_CmpFunc || (m_CmpFuncWithStats && m_LogStream))) {
fprintf(stderr, "Incorrect thread function pointer.\n");
return;
}
while(1) {
// Wait for signal to start work...
m_StartBarrier->Wait();
if(*m_ParentExitFlag) {
return;
}
if(m_CmpFunc)
(*m_CmpFunc)(m_Job);
else
(*m_CmpFuncWithStats)(m_Job, m_LogStream);
{
TCLock lock(*m_ParentCounterLock);
(*m_ParentCounter)++;
}
m_FinishCV->NotifyOne();
}
}
ThreadGroup::ThreadGroup(uint32 numThreads,
const CompressionJob &job,
CompressionFunc func)
: m_StartBarrier(new TCBarrier(numThreads + 1))
, m_FinishMutex(new TCMutex())
, m_FinishCV(new TCConditionVariable())
, m_NumThreads(numThreads)
, m_ActiveThreads(0)
, m_Job(job)
, m_ThreadState(eThreadState_Done)
, m_ExitFlag(false)
{
for(uint32 i = 0; i < kMaxNumThreads; i++) {
// Thread synchronization primitives
m_Threads[i].m_ParentCounterLock = m_FinishMutex;
m_Threads[i].m_FinishCV = m_FinishCV;
m_Threads[i].m_ParentCounter = &m_ThreadsFinished;
m_Threads[i].m_StartBarrier = m_StartBarrier;
m_Threads[i].m_ParentExitFlag = &m_ExitFlag;
m_Threads[i].m_CmpFunc = func;
}
}
ThreadGroup::ThreadGroup(
uint32 numThreads,
const CompressionJob &job,
CompressionFuncWithStats func,
std::ostream *logStream
)
: m_StartBarrier(new TCBarrier(numThreads + 1))
, m_FinishMutex(new TCMutex())
, m_FinishCV(new TCConditionVariable())
, m_NumThreads(numThreads)
, m_ActiveThreads(0)
, m_Job(job)
, m_ThreadState(eThreadState_Done)
, m_ExitFlag(false)
{
for(uint32 i = 0; i < kMaxNumThreads; i++) {
// Thread synchronization primitives
m_Threads[i].m_ParentCounterLock = m_FinishMutex;
m_Threads[i].m_FinishCV = m_FinishCV;
m_Threads[i].m_ParentCounter = &m_ThreadsFinished;
m_Threads[i].m_StartBarrier = m_StartBarrier;
m_Threads[i].m_ParentExitFlag = &m_ExitFlag;
m_Threads[i].m_CmpFuncWithStats = func;
m_Threads[i].m_LogStream = logStream;
}
}
ThreadGroup::~ThreadGroup() {
delete m_StartBarrier;
delete m_FinishMutex;
delete m_FinishCV;
}
bool ThreadGroup::PrepareThreads() {
// Make sure that threads aren't running.
if(m_ThreadState != eThreadState_Done) {
return false;
}
// Have we already activated the thread group?
if(m_ActiveThreads > 0) {
m_ThreadState = eThreadState_Waiting;
return true;
}
// We can assume that the image data is in block stream order
// so, the size of the data given to each thread will be (nb*4)x4
uint32 blockDim[2];
GetBlockDimensions(m_Job.Format(), blockDim);
uint32 numBlocks = (m_Job.Width() * m_Job.Height()) / (blockDim[0] * blockDim[1]);
uint32 blocksProcessed = 0;
uint32 blocksPerThread = (numBlocks/m_NumThreads) + ((numBlocks % m_NumThreads)? 1 : 0);
// Currently no threads are finished...
m_ThreadsFinished = 0;
for(int i = 0; i < m_NumThreads; i++) {
if(m_ActiveThreads >= kMaxNumThreads)
break;
int numBlocksThisThread = blocksPerThread;
if(blocksProcessed + numBlocksThisThread > numBlocks) {
numBlocksThisThread = numBlocks - blocksProcessed;
}
uint32 start[2], end[2];
m_Job.BlockIdxToCoords(blocksProcessed, start);
m_Job.BlockIdxToCoords(blocksProcessed + numBlocksThisThread, end);
// !TODO! This should be moved to a unit test...
assert(m_Job.CoordsToBlockIdx(start[0], start[1]) == blocksProcessed);
assert(m_Job.CoordsToBlockIdx(end[0], end[1]) == blocksProcessed + numBlocksThisThread);
CompressionJob cj(m_Job.Format(),
m_Job.InBuf(), m_Job.OutBuf(),
m_Job.Width(), m_Job.Height(),
start[0], start[1],
end[0], end[1]);
CmpThread &t = m_Threads[m_ActiveThreads];
t.m_Job = cj;
blocksProcessed += numBlocksThisThread;
m_ThreadHandles[m_ActiveThreads] = new TCThread(t);
m_ActiveThreads++;
}
m_ThreadState = eThreadState_Waiting;
return true;
}
bool ThreadGroup::Start() {
if(m_ActiveThreads <= 0) {
return false;
}
if(m_ThreadState != eThreadState_Waiting) {
return false;
}
m_StopWatch.Reset();
m_StopWatch.Start();
// Last thread to activate the barrier is this one.
m_ThreadState = eThreadState_Running;
m_StartBarrier->Wait();
return true;
}
bool ThreadGroup::CleanUpThreads() {
// Are the threads currently running?
if(m_ThreadState == eThreadState_Running) {
// ... if so, wait for them to finish
Join();
}
assert(m_ThreadState == eThreadState_Done || m_ThreadState == eThreadState_Waiting);
// Mark all threads for exit
m_ExitFlag = true;
// Hit the barrier to signal them to go.
m_StartBarrier->Wait();
// Clean up.
for(uint32 i = 0; i < m_ActiveThreads; i++) {
m_ThreadHandles[i]->Join();
delete m_ThreadHandles[i];
}
// Reset active number of threads...
m_ActiveThreads = 0;
m_ExitFlag = false;
return true;
}
void ThreadGroup::Join() {
TCLock lock(*m_FinishMutex);
while(m_ThreadsFinished != m_ActiveThreads) {
m_FinishCV->Wait(lock);
}
m_StopWatch.Stop();
m_ThreadState = eThreadState_Done;
m_ThreadsFinished = 0;
}

View file

@ -1,105 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#ifndef _THREAD_GROUP_H_
#define _THREAD_GROUP_H_
#include "FasTC/StopWatch.h"
#include "CompressionFuncs.h"
#include "Thread.h"
#include <iosfwd>
struct CmpThread : public TCCallable {
friend class ThreadGroup;
private:
uint32 *m_ParentCounter;
TCBarrier *m_StartBarrier;
TCMutex *m_ParentCounterLock;
TCConditionVariable *m_FinishCV;
bool *m_ParentExitFlag;
FasTC::CompressionJob m_Job;
CompressionFunc m_CmpFunc;
CompressionFuncWithStats m_CmpFuncWithStats;
std::ostream *m_LogStream;
CmpThread();
public:
virtual ~CmpThread() { }
virtual void operator ()();
};
class ThreadGroup {
public:
ThreadGroup(
uint32 numThreads,
const FasTC::CompressionJob &cj,
CompressionFunc func
);
ThreadGroup(
uint32 numThreads,
const FasTC::CompressionJob &cj,
CompressionFuncWithStats func,
std::ostream *logStream
);
~ThreadGroup();
bool PrepareThreads();
bool Start();
void Join();
bool CleanUpThreads();
const StopWatch &GetStopWatch() const { return m_StopWatch; }
enum EThreadState {
eThreadState_Waiting,
eThreadState_Running,
eThreadState_Done
};
private:
TCBarrier *const m_StartBarrier;
TCMutex *const m_FinishMutex;
TCConditionVariable *const m_FinishCV;
static const uint32 kMaxNumThreads = 256;
const int m_NumThreads;
uint32 m_ActiveThreads;
uint32 m_ThreadsFinished;
CmpThread m_Threads[kMaxNumThreads];
TCThread *m_ThreadHandles[kMaxNumThreads];
FasTC::CompressionJob m_Job;
StopWatch m_StopWatch;
EThreadState m_ThreadState;
bool m_ExitFlag;
};
#endif // _THREAD_GROUP_H_

View file

@ -1,287 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "Thread.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#ifdef __APPLE__
#include <sched.h>
#endif
static void ReportErrorAndExit(int err, const char *msg) {
char errMsg[1024];
sprintf(errMsg, "Thread error -- %s: ", msg);
errno = err;
perror(errMsg);
exit(1);
}
////////////////////////////////////////////////////////////////////////////////
//
// Thread Implementation
//
////////////////////////////////////////////////////////////////////////////////
class TCThreadImpl : public TCThreadBaseImpl {
private:
static void *RunThread(void *arg) {
TCThreadImpl *impl = (TCThreadImpl *)arg;
impl->m_Callable();
return NULL;
}
pthread_t m_ThreadID;
TCCallable &m_Callable;
public:
TCThreadImpl(TCCallable &callable) :
m_Callable(callable)
{
int result = pthread_create(&m_ThreadID, NULL, RunThread, (void *)this);
if(result != 0) {
ReportErrorAndExit(result, "pthread_create");
}
}
virtual ~TCThreadImpl() { }
void Join() {
void *status;
int result = pthread_join(m_ThreadID, &status);
if(result != 0) {
ReportErrorAndExit(result, "pthread_join");
}
}
};
class TCThreadImplFactory : public TCThreadBaseImplFactory {
TCCallable &m_Callable;
public:
TCThreadImplFactory(TCCallable &callable) : m_Callable(callable) { }
virtual ~TCThreadImplFactory() { }
virtual TCThreadBaseImpl *CreateImpl() const {
return new TCThreadImpl(m_Callable);
}
};
TCThread::TCThread(TCCallable &callable)
: TCThreadBase(TCThreadImplFactory(callable))
{ }
void TCThread::Join() {
CheckReferenceCount();
((TCThreadImpl *)m_Impl)->Join();
}
#ifdef WIN32
#undef Yield
#endif
void TCThread::Yield() {
#if defined(__APPLE__) || defined(__MINGW32__)
int result = sched_yield();
#else
int result = pthread_yield();
#endif
if(result != 0) {
ReportErrorAndExit(result, "pthread_yield");
}
}
uint64 TCThread::ThreadID() {
#ifdef __MINGW32__
return static_cast<uint64>(pthread_self().x);
#elif defined __APPLE__
return reinterpret_cast<uint64>(pthread_self());
#else
return static_cast<uint64>(pthread_self());
#endif
}
////////////////////////////////////////////////////////////////////////////////
//
// Mutex Implementation
//
////////////////////////////////////////////////////////////////////////////////
class TCMutexImpl : public TCThreadBaseImpl {
private:
pthread_mutex_t m_Mutex;
public:
pthread_mutex_t *GetMutex() { return &m_Mutex; }
TCMutexImpl() : TCThreadBaseImpl() {
int result = pthread_mutex_init( &m_Mutex, NULL );
if(result != 0) {
ReportErrorAndExit(result, "pthread_mutex_init");
}
}
virtual ~TCMutexImpl() {
int result = pthread_mutex_destroy( &m_Mutex );
if(result != 0) {
ReportErrorAndExit(result, "pthread_mutex_destroy");
}
}
};
class TCMutexImplFactory : public TCThreadBaseImplFactory {
public:
TCMutexImplFactory() { }
virtual ~TCMutexImplFactory() { }
virtual TCThreadBaseImpl *CreateImpl() const {
return new TCMutexImpl();
}
};
TCMutex::TCMutex() : TCThreadBase(TCMutexImplFactory())
{ }
////////////////////////////////////////////////////////////////////////////////
//
// Lock Implementation
//
////////////////////////////////////////////////////////////////////////////////
class TCLockImpl : public TCThreadBaseImpl {
private:
pthread_mutex_t *const m_MutexPtr;
public:
TCLockImpl(TCMutex &mutex)
: m_MutexPtr(((TCMutexImpl *)(mutex.m_Impl))->GetMutex())
{
int result = pthread_mutex_lock( m_MutexPtr );
if(result != 0) {
ReportErrorAndExit(result, "pthread_mutex_lock");
}
}
virtual ~TCLockImpl() {
int result = pthread_mutex_unlock( m_MutexPtr );
if(result != 0) {
ReportErrorAndExit(result, "pthread_mutex_unlock");
}
}
pthread_mutex_t *GetMutexPtr() const { return m_MutexPtr; }
};
class TCLockImplFactory : public TCThreadBaseImplFactory {
private:
TCMutex &m_Mutex;
public:
TCLockImplFactory(TCMutex &mutex) : m_Mutex(mutex){ }
virtual ~TCLockImplFactory() { }
virtual TCThreadBaseImpl *CreateImpl() const {
return new TCLockImpl(m_Mutex);
}
};
TCLock::TCLock(TCMutex &mutex) : TCThreadBase(TCLockImplFactory(mutex))
{ }
////////////////////////////////////////////////////////////////////////////////
//
// Condition Variable Implementation
//
////////////////////////////////////////////////////////////////////////////////
class TCConditionVariableImpl : public TCThreadBaseImpl {
private:
pthread_cond_t m_CV;
public:
TCConditionVariableImpl() {
int result = pthread_cond_init( &m_CV, NULL );
if(result != 0) {
ReportErrorAndExit(result, "pthread_cond_init");
}
}
virtual ~TCConditionVariableImpl() {
int result = pthread_cond_destroy( &m_CV );
if(result != 0) {
ReportErrorAndExit(result, "pthread_cond_destroy");
}
}
void Wait(TCLock &lock) {
TCLockImpl *lockImpl = (TCLockImpl *)(lock.m_Impl);
int result = pthread_cond_wait( &m_CV, lockImpl->GetMutexPtr() );
if(result != 0) {
ReportErrorAndExit( result, "pthread_cond_wait" );
}
}
void NotifyOne() {
int result = pthread_cond_signal( &m_CV );
if(result != 0) {
ReportErrorAndExit( result, "pthread_cond_signal" );
}
}
void NotifyAll() {
int result = pthread_cond_broadcast( &m_CV );
if(result != 0) {
ReportErrorAndExit( result, "pthread_cond_broadcast" );
}
}
};
class TCConditionVariableImplFactory : public TCThreadBaseImplFactory {
public:
TCConditionVariableImplFactory() { }
virtual ~TCConditionVariableImplFactory() { }
virtual TCThreadBaseImpl *CreateImpl() const {
return new TCConditionVariableImpl();
}
};
TCConditionVariable::TCConditionVariable()
: TCThreadBase(TCConditionVariableImplFactory())
{ }
void TCConditionVariable::Wait(TCLock &lock) {
CheckReferenceCount();
TCConditionVariableImpl *impl = (TCConditionVariableImpl *)m_Impl;
impl->Wait(lock);
}
void TCConditionVariable::NotifyOne() {
CheckReferenceCount();
TCConditionVariableImpl *impl = (TCConditionVariableImpl *)m_Impl;
impl->NotifyOne();
}
void TCConditionVariable::NotifyAll() {
CheckReferenceCount();
TCConditionVariableImpl *impl = (TCConditionVariableImpl *)m_Impl;
impl->NotifyAll();
}

View file

@ -1,47 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "FasTC/ThreadSafeStreambuf.h"
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <sstream>
#include <string>
#include "Thread.h"
ThreadSafeStreambuf::ThreadSafeStreambuf(std::ostream &sink)
: ::std::streambuf()
, m_Sink(sink)
, m_Mutex(new TCMutex)
{ }
ThreadSafeStreambuf::~ThreadSafeStreambuf() {
if(m_Mutex) {
delete m_Mutex;
}
}
::std::streamsize ThreadSafeStreambuf::xsputn(const char_type *s,
::std::streamsize count) {
// Lock it.
TCLock lock(*m_Mutex);
::std::streambuf *sinkStream = m_Sink.rdbuf();
return sinkStream->sputn(s, count);
}

View file

@ -1,255 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "Thread.h"
#include <assert.h>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <tchar.h>
#include <strsafe.h>
void ErrorHandler(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code.
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message.
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK);
// Free error-handling buffer allocations.
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
////////////////////////////////////////////////////////////////////////////////
//
// Thread Implementation
//
////////////////////////////////////////////////////////////////////////////////
class TCThreadImpl : public TCThreadBaseImpl {
private:
static DWORD WINAPI RunThread(LPVOID arg) {
TCThreadImpl *impl = (TCThreadImpl *)arg;
impl->m_Callable();
return 0;
}
HANDLE m_ThreadID;
TCCallable &m_Callable;
public:
TCThreadImpl(TCCallable &callable) :
m_Callable(callable)
{
m_ThreadID = CreateThread(NULL, 0, RunThread, (void *)this, 0, 0);
if(m_ThreadID == NULL) {
ErrorHandler("CreateThread");
}
}
virtual ~TCThreadImpl() { }
void Join() {
DWORD result = WaitForSingleObject(m_ThreadID, INFINITE);
if(result == WAIT_FAILED) {
ErrorHandler("WaitForSingleObject");
}
}
};
class TCThreadImplFactory : public TCThreadBaseImplFactory {
TCCallable &m_Callable;
public:
TCThreadImplFactory(TCCallable &callable) : m_Callable(callable) { }
virtual ~TCThreadImplFactory() { }
virtual TCThreadBaseImpl *CreateImpl() const {
return new TCThreadImpl(m_Callable);
}
};
TCThread::TCThread(TCCallable &callable)
: TCThreadBase(TCThreadImplFactory(callable))
{ }
void TCThread::Join() {
CheckReferenceCount();
((TCThreadImpl *)m_Impl)->Join();
}
// !HACK! wtf, Microsoft?
#undef Yield
void TCThread::Yield() {
if(!SwitchToThread()) {
ErrorHandler("SwitchToThread");
}
}
uint64 TCThread::ThreadID() {
return static_cast<uint64>(GetCurrentThreadId());
}
////////////////////////////////////////////////////////////////////////////////
//
// Mutex Implementation
//
////////////////////////////////////////////////////////////////////////////////
class TCMutexImpl : public TCThreadBaseImpl {
private:
CRITICAL_SECTION m_CS;
public:
LPCRITICAL_SECTION GetMutex() { return &m_CS; }
TCMutexImpl() : TCThreadBaseImpl() {
InitializeCriticalSection( &m_CS );
}
virtual ~TCMutexImpl() {
DeleteCriticalSection( &m_CS );
}
};
class TCMutexImplFactory : public TCThreadBaseImplFactory {
public:
TCMutexImplFactory() { }
virtual ~TCMutexImplFactory() { }
virtual TCThreadBaseImpl *CreateImpl() const {
return new TCMutexImpl();
}
};
TCMutex::TCMutex() : TCThreadBase(TCMutexImplFactory())
{ }
////////////////////////////////////////////////////////////////////////////////
//
// Lock Implementation
//
////////////////////////////////////////////////////////////////////////////////
class TCLockImpl : public TCThreadBaseImpl {
private:
LPCRITICAL_SECTION const m_CSPtr;
// Disallow copy and assign...
TCLockImpl(const TCLockImpl &) : m_CSPtr(NULL) { }
TCLockImpl &operator =(const TCLockImpl &) { return *this; }
public:
TCLockImpl(TCMutex &mutex)
: m_CSPtr(((TCMutexImpl *)(mutex.m_Impl))->GetMutex()) {
EnterCriticalSection( m_CSPtr );
}
virtual ~TCLockImpl() { LeaveCriticalSection( m_CSPtr ); }
LPCRITICAL_SECTION GetMutexPtr() const { return m_CSPtr; }
};
class TCLockImplFactory : public TCThreadBaseImplFactory {
private:
TCMutex &m_Mutex;
public:
TCLockImplFactory(TCMutex &mutex) : m_Mutex(mutex){ }
virtual ~TCLockImplFactory() { }
virtual TCThreadBaseImpl *CreateImpl() const {
return new TCLockImpl(m_Mutex);
}
};
TCLock::TCLock(TCMutex &mutex) : TCThreadBase(TCLockImplFactory(mutex))
{ }
////////////////////////////////////////////////////////////////////////////////
//
// Condition Variable Implementation
//
////////////////////////////////////////////////////////////////////////////////
class TCConditionVariableImpl : public TCThreadBaseImpl {
private:
CONDITION_VARIABLE m_CV;
public:
TCConditionVariableImpl() { InitializeConditionVariable( &m_CV ); }
virtual ~TCConditionVariableImpl() {
// No destroy condition variable...?
}
void Wait(TCLock &lock) {
TCLockImpl *lockImpl = (TCLockImpl *)(lock.m_Impl);
BOOL result = SleepConditionVariableCS( &m_CV, lockImpl->GetMutexPtr(), INFINITE );
if(!result) {
ErrorHandler( "SleepConditionVariableCS" );
}
}
void NotifyOne() { WakeConditionVariable( &m_CV ); }
void NotifyAll() { WakeAllConditionVariable( &m_CV ); }
};
class TCConditionVariableImplFactory : public TCThreadBaseImplFactory {
public:
TCConditionVariableImplFactory() { }
virtual ~TCConditionVariableImplFactory() { }
virtual TCThreadBaseImpl *CreateImpl() const {
return new TCConditionVariableImpl();
}
};
TCConditionVariable::TCConditionVariable()
: TCThreadBase(TCConditionVariableImplFactory())
{ }
void TCConditionVariable::Wait(TCLock &lock) {
CheckReferenceCount();
TCConditionVariableImpl *impl = (TCConditionVariableImpl *)m_Impl;
impl->Wait(lock);
}
void TCConditionVariable::NotifyOne() {
CheckReferenceCount();
TCConditionVariableImpl *impl = (TCConditionVariableImpl *)m_Impl;
impl->NotifyOne();
}
void TCConditionVariable::NotifyAll() {
CheckReferenceCount();
TCConditionVariableImpl *impl = (TCConditionVariableImpl *)m_Impl;
impl->NotifyAll();
}

View file

@ -1,260 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "WorkerQueue.h"
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <iostream>
#include "FasTC/BPTCCompressor.h"
using FasTC::CompressionJob;
template <typename T>
static inline void clamp(T &x, const T &min, const T &max) {
if(x < min) x = min;
else if(x > max) x = max;
}
WorkerThread::WorkerThread(WorkerQueue * parent, uint32 idx)
: TCCallable()
, m_ThreadIdx(idx)
, m_Parent(parent)
{ }
void WorkerThread::operator()() {
if(!m_Parent) {
fprintf(stderr, "%s\n", "Illegal worker thread initialization -- parent is NULL.");
return;
}
CompressionFunc f = m_Parent->GetCompressionFunc();
CompressionFuncWithStats fStat = m_Parent->GetCompressionFuncWithStats();
std::ostream *logStream = m_Parent->GetLogStream();
if(!(f || (fStat && logStream))) {
fprintf(stderr, "%s\n", "Illegal worker queue initialization -- compression func is NULL.");
return;
}
bool quitFlag = false;
while(!quitFlag) {
switch(m_Parent->AcceptThreadData(m_ThreadIdx)) {
case eAction_Quit:
{
quitFlag = true;
break;
}
case eAction_Wait:
{
TCThread::Yield();
break;
}
case eAction_DoWork:
{
const CompressionJob &job = m_Parent->GetCompressionJob();
uint32 start[2];
m_Parent->GetStartForThread(m_ThreadIdx, start);
uint32 end[2];
m_Parent->GetEndForThread(m_ThreadIdx, end);
CompressionJob cj (job.Format(),
job.InBuf(), job.OutBuf(),
job.Width(), job.Height(),
start[0], start[1],
end[0], end[1]);
if(f)
(*f)(cj);
else
(*fStat)(cj, logStream);
break;
}
default:
{
fprintf(stderr, "Unrecognized thread command!\n");
quitFlag = true;
break;
}
}
}
m_Parent->NotifyWorkerFinished();
return;
}
WorkerQueue::WorkerQueue(
uint32 numCompressions,
uint32 numThreads,
uint32 jobSize,
const CompressionJob &job,
CompressionFunc func
)
: m_NumCompressions(0)
, m_TotalNumCompressions(std::max(uint32(1), numCompressions))
, m_NumThreads(numThreads)
, m_WaitingThreads(0)
, m_ActiveThreads(0)
, m_JobSize(std::max(uint32(1), jobSize))
, m_Job(job)
, m_NextBlock(0)
, m_CompressionFunc(func)
, m_CompressionFuncWithStats(NULL)
, m_LogStream(NULL)
{
clamp(m_NumThreads, uint32(1), uint32(kMaxNumWorkerThreads));
}
WorkerQueue::WorkerQueue(
uint32 numCompressions,
uint32 numThreads,
uint32 jobSize,
const CompressionJob &job,
CompressionFuncWithStats func,
std::ostream *logStream
)
: m_NumCompressions(0)
, m_TotalNumCompressions(std::max(uint32(1), numCompressions))
, m_NumThreads(numThreads)
, m_WaitingThreads(0)
, m_ActiveThreads(0)
, m_JobSize(std::max(uint32(1), jobSize))
, m_Job(job)
, m_NextBlock(0)
, m_CompressionFunc(NULL)
, m_CompressionFuncWithStats(func)
, m_LogStream(logStream)
{
clamp(m_NumThreads, uint32(1), uint32(kMaxNumWorkerThreads));
}
void WorkerQueue::Run() {
// Spawn a bunch of threads...
TCLock lock(m_Mutex);
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++;
}
m_StopWatch.Reset();
m_StopWatch.Start();
m_NextBlock = 0;
m_WaitingThreads = 0;
// Wait for them to finish...
while(m_ActiveThreads > 0) {
m_CV.Wait(lock);
}
m_StopWatch.Stop();
// Join them all together..
for(uint32 i = 0; i < m_NumThreads; i++) {
m_ThreadHandles[i]->Join();
delete m_ThreadHandles[i];
delete m_Workers[i];
}
}
void WorkerQueue::NotifyWorkerFinished() {
{
TCLock lock(m_Mutex);
m_ActiveThreads--;
}
m_CV.NotifyOne();
}
WorkerThread::EAction WorkerQueue::AcceptThreadData(uint32 threadIdx) {
if(threadIdx >= m_ActiveThreads) {
return WorkerThread::eAction_Quit;
}
// How many blocks total do we have?
uint32 blockDim[2];
GetBlockDimensions(m_Job.Format(), blockDim);
const uint32 totalBlocks = (m_Job.Width() * m_Job.Height()) / (blockDim[0] * blockDim[1]);
// Make sure we have exclusive access...
TCLock lock(m_Mutex);
// If we've completed all blocks, then mark the thread for
// completion.
if(m_NextBlock == totalBlocks) {
if(m_NumCompressions < m_TotalNumCompressions) {
if(++m_WaitingThreads == m_ActiveThreads) {
m_NextBlock = 0;
m_WaitingThreads = 0;
} else {
return WorkerThread::eAction_Wait;
}
}
else {
return WorkerThread::eAction_Quit;
}
}
// Otherwise, this thread's offset is the current block...
m_Offsets[threadIdx] = m_NextBlock;
// The number of blocks to process is either the job size
// or the number of blocks remaining.
int blocksProcessed = std::min(m_JobSize, totalBlocks - m_NextBlock);
m_NumBlocks[threadIdx] = blocksProcessed;
// Make sure the next block is updated.
m_NextBlock += blocksProcessed;
if(m_NextBlock == totalBlocks) {
++m_NumCompressions;
}
return WorkerThread::eAction_DoWork;
}
void WorkerQueue::GetStartForThread(const uint32 threadIdx, uint32 (&start)[2]) {
assert(threadIdx >= 0);
assert(threadIdx < m_NumThreads);
assert(m_Offsets[threadIdx] >= 0);
const uint32 blockIdx = m_Offsets[threadIdx];
m_Job.BlockIdxToCoords(blockIdx, start);
}
void WorkerQueue::GetEndForThread(const uint32 threadIdx, uint32 (&end)[2]) {
assert(threadIdx >= 0);
assert(threadIdx < m_NumThreads);
assert(m_Offsets[threadIdx] >= 0);
assert(m_NumBlocks[threadIdx] >= 0);
const uint32 blockIdx = m_Offsets[threadIdx] + m_NumBlocks[threadIdx];
m_Job.BlockIdxToCoords(blockIdx, end);
}

View file

@ -1,120 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#ifndef __TEXCOMP_WORKDER_QUEUE_H__
#define __TEXCOMP_WORKDER_QUEUE_H__
// Forward declare...
class WorkerQueue;
// Necessary includes...
#include "FasTC/TexCompTypes.h"
#include "FasTC/StopWatch.h"
#include "Thread.h"
#include "CompressionFuncs.h"
#include <iosfwd>
class WorkerThread : public TCCallable {
friend class WorkerQueue;
public:
WorkerThread(WorkerQueue *, uint32 idx);
virtual ~WorkerThread() { }
virtual void operator ()();
enum EAction {
eAction_Wait,
eAction_DoWork,
eAction_Quit,
kNumWorkerThreadActions
};
private:
uint32 m_ThreadIdx;
WorkerQueue *const m_Parent;
};
class WorkerQueue {
friend class WorkerThread;
public:
WorkerQueue(
uint32 numCompressions,
uint32 numThreads,
uint32 jobSize,
const FasTC::CompressionJob &job,
CompressionFunc func
);
WorkerQueue(
uint32 numCompressions,
uint32 numThreads,
uint32 jobSize,
const FasTC::CompressionJob &job,
CompressionFuncWithStats func,
std::ostream *logStream
);
~WorkerQueue() { }
// Runs the workers
void Run();
const StopWatch &GetStopWatch() const { return m_StopWatch; }
private:
uint32 m_NumCompressions;
const uint32 m_TotalNumCompressions;
uint32 m_NumThreads;
uint32 m_WaitingThreads;
uint32 m_ActiveThreads;
uint32 m_JobSize;
FasTC::CompressionJob m_Job;
TCConditionVariable m_CV;
TCMutex m_Mutex;
uint32 m_NextBlock;
static const int kMaxNumWorkerThreads = 256;
uint32 m_Offsets[kMaxNumWorkerThreads];
uint32 m_NumBlocks[kMaxNumWorkerThreads];
WorkerThread *m_Workers[kMaxNumWorkerThreads];
TCThread *m_ThreadHandles[kMaxNumWorkerThreads];
const FasTC::CompressionJob &GetCompressionJob() const { return m_Job; }
void GetStartForThread(const uint32 threadIdx, uint32 (&start)[2]);
void GetEndForThread(const uint32 threadIdx, uint32 (&start)[2]);
const CompressionFunc m_CompressionFunc;
CompressionFunc GetCompressionFunc() const { return m_CompressionFunc; }
const CompressionFuncWithStats m_CompressionFuncWithStats;
CompressionFuncWithStats GetCompressionFuncWithStats() const { return m_CompressionFuncWithStats; }
std::ostream *m_LogStream;
std::ostream *GetLogStream() const { return m_LogStream; }
StopWatch m_StopWatch;
WorkerThread::EAction AcceptThreadData(uint32 threadIdx);
void NotifyWorkerFinished();
};
#endif //__TEXCOMP_WORKDER_QUEUE_H__

View file

@ -1,43 +0,0 @@
# Copyright 2016 The University of North Carolina at Chapel Hill
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Please send all BUG REPORTS to <pavel@cs.unc.edu>.
# <http://gamma.cs.unc.edu/FasTC/>
SET( LIBRARY_HEADERS
"include/FasTC/DXTCompressor.h"
)
SET( SOURCES
"src/Compressor.cpp"
"src/Decompressor.cpp"
)
INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Base/include)
INCLUDE_DIRECTORIES(${FasTC_BINARY_DIR}/Base/include)
INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/DXTEncoder/include)
INCLUDE_DIRECTORIES(${FasTC_BINARY_DIR}/DXTEncoder/include)
ADD_LIBRARY( DXTEncoder
${HEADERS}
${SOURCES}
)
INSTALL(TARGETS DXTEncoder EXPORT FasTCTargets ARCHIVE DESTINATION lib COMPONENT lib)
INSTALL(
FILES ${LIBRARY_HEADERS}
DESTINATION ${INCLUDE_INSTALL_DIR}/FasTC
COMPONENT dev)
TARGET_LINK_LIBRARIES( DXTEncoder FasTCBase )

View file

@ -1,29 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "FasTC/TexCompTypes.h"
#include "FasTC/CompressionJob.h"
namespace DXTC
{
// DXT compressor
void CompressImageDXT1(const FasTC::CompressionJob &);
void CompressImageDXT5(const FasTC::CompressionJob &);
void DecompressDXT1(const FasTC::DecompressionJob &);
void DecompressDXT5(const FasTC::DecompressionJob &);
}

View file

@ -1,96 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "FasTC/DXTCompressor.h"
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <cstring>
#define STB_DXT_IMPLEMENTATION
#include "stb_dxt.h"
namespace DXTC
{
// Function prototypes
void ExtractBlock(const uint32* inPtr, uint32 width, uint8* colorBlock);
// Extract a 4 by 4 block of pixels from inPtr and store it in colorBlock. The width parameter
// specifies the size of the image in pixels.
void ExtractBlock(const uint32* inPtr, uint32 width, uint8* colorBlock)
{
for (int j = 0; j < 4; j++)
{
memcpy(&colorBlock[j * 4 * 4], inPtr, 4 * 4);
inPtr += width;
}
}
// Compress an image using DXT1 compression. Use the inBuf parameter to point to an image in
// 4-byte RGBA format. The width and height parameters specify the size of the image in pixels.
// The buffer pointed to by outBuf should be large enough to store the compressed image. This
// implementation has an 8:1 compression ratio.
void CompressImageDXT1(const FasTC::CompressionJob &cj) {
uint8 block[64];
const uint32 kBlockSz = GetBlockSize(FasTC::eCompressionFormat_DXT1);
const uint32 startBlock = cj.CoordsToBlockIdx(cj.XStart(), cj.YStart());
uint8 *outBuf = cj.OutBuf() + startBlock * kBlockSz;
const uint32 *inPixels = reinterpret_cast<const uint32 *>(cj.InBuf());
uint32 endY = std::min(cj.YEnd(), cj.Height() - 4);
uint32 startX = cj.XStart();
for(uint32 j = cj.YStart(); j <= endY; j += 4) {
const uint32 endX = j == cj.YEnd()? cj.XEnd() : cj.Width();
for(uint32 i = startX; i < endX; i += 4) {
const uint32 kOffset = j*cj.Width() + i;
ExtractBlock(inPixels + kOffset, cj.Width(), block);
stb_compress_dxt_block(outBuf, block, 0, STB_DXT_DITHER);
outBuf += 8;
}
startX = 0;
}
}
// Compress an image using DXT5 compression. Use the inBuf parameter to point to an image in
// 4-byte RGBA format. The width and height parameters specify the size of the image in pixels.
// The buffer pointed to by outBuf should be large enough to store the compressed image. This
// implementation has an 4:1 compression ratio.
void CompressImageDXT5(const FasTC::CompressionJob &cj) {
uint8 block[64];
const uint32 kBlockSz = GetBlockSize(FasTC::eCompressionFormat_DXT5);
const uint32 startBlock = cj.CoordsToBlockIdx(cj.XStart(), cj.YStart());
uint8 *outBuf = cj.OutBuf() + startBlock * kBlockSz;
const uint32 *inPixels = reinterpret_cast<const uint32 *>(cj.InBuf());
uint32 endY = std::min(cj.YEnd(), cj.Height() - 4);
uint32 startX = cj.XStart();
for(uint32 j = cj.YStart(); j <= endY; j += 4) {
const uint32 endX = j == cj.YEnd()? cj.XEnd() : cj.Width();
for(uint32 i = startX; i < endX; i += 4) {
const uint32 kOffset = j*cj.Width() + i;
ExtractBlock(inPixels + kOffset, cj.Width(), block);
stb_compress_dxt_block(outBuf, block, 1, STB_DXT_DITHER);
outBuf += 16;
}
startX = 0;
}
}
}

View file

@ -1,156 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "FasTC/DXTCompressor.h"
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include "FasTC/Pixel.h"
namespace {
void DecompressDXT1Block(const uint8 *block, uint32 *outBuf, bool check_order) {
// When we call FasTC::Pixel::FromBits, we expect the bits
// to be read out of memory in LSB (byte) order first. Hence,
// we can't read the blocks directly as uint16 values out of
// the DXT buffer and we have to swap the bytes before hand.
uint16 colorA = block[1] | block[0] << 8;
uint16 colorB = block[3] | block[2] << 8;
uint32 mod = reinterpret_cast<const uint32 *>(block + 4)[0];
uint8 kFiveSixFive[4] = { 0, 5, 6, 5 };
FasTC::Pixel a, b, c, d;
a.FromBits(reinterpret_cast<const uint8 *>(&colorA), kFiveSixFive);
b.FromBits(reinterpret_cast<const uint8 *>(&colorB), kFiveSixFive);
uint8 kFullDepth[4] = { 8, 8, 8, 8 };
a.ChangeBitDepth(kFullDepth);
b.ChangeBitDepth(kFullDepth);
// However, for the purposes of properly decoding DXT, we can read them as ints...
const uint16 *block_ptr = reinterpret_cast<const uint16 *>(block);
if (!check_order || block_ptr[0] > block_ptr[1]) {
c = (a * 2 + b) / 3;
d = (a + b * 2) / 3;
}
else {
c = (a + b) / 2;
// d already initialized to zero...
}
FasTC::Pixel *colors[4] = { &a, &b, &c, &d };
uint32 *outPixels = reinterpret_cast<uint32 *>(outBuf);
for (uint32 i = 0; i < 16; i++) {
outPixels[i] &= 0xFF000000;
outPixels[i] |= colors[(mod >> (i * 2)) & 3]->Pack() & 0x00FFFFFF;
}
}
void DecompressDXT5Block(const uint8 *block, uint32 *outBuf) {
int alpha0 = block[0];
int alpha1 = block[1];
int palette[8];
palette[0] = alpha0;
palette[1] = alpha1;
if (alpha0 > alpha1) {
for (int i = 2; i < 8; ++i) {
palette[i] = ((8 - i) * alpha0 + (i - 1) * alpha1) / 7;
}
} else {
for (int i = 2; i < 6; ++i) {
palette[i] = ((6 - i) * alpha0 + (i - 1) * alpha1) / 5;
}
palette[6] = 0;
palette[7] = 255;
}
uint64 mod = *reinterpret_cast<const uint64 *>(block) >> 16;
uint32 *outPixels = reinterpret_cast<uint32 *>(outBuf);
for (uint32 i = 0; i < 16; i++) {
outPixels[i] &= 0x00FFFFFF;
outPixels[i] |= palette[(mod >> (i * 3)) & 7] << 24;
}
}
} // namespace
namespace DXTC
{
void DecompressDXT1(const FasTC::DecompressionJob &dcj) {
uint32 blockW = (dcj.Width() + 3) >> 2;
uint32 blockH = (dcj.Height() + 3) >> 2;
const uint32 blockSz = GetBlockSize(FasTC::eCompressionFormat_DXT1);
uint32 *outPixels = reinterpret_cast<uint32 *>(dcj.OutBuf());
uint32 outBlock[16];
memset(outBlock, 0xFF, sizeof(outBlock));
for(uint32 j = 0; j < blockH; j++) {
for(uint32 i = 0; i < blockW; i++) {
uint32 offset = (j * blockW + i) * blockSz;
DecompressDXT1Block(dcj.InBuf() + offset, outBlock, true);
uint32 decompWidth = std::min(4U, dcj.Width() - i * 4);
uint32 decompHeight = std::min(4U, dcj.Height() - j * 4);
for(uint32 y = 0; y < decompHeight; y++)
for(uint32 x = 0; x < decompWidth; x++) {
offset = (j*4 + y)*dcj.Width() + ((i*4)+x);
outPixels[offset] = outBlock[y*4 + x];
}
}
}
}
void DecompressDXT5(const FasTC::DecompressionJob &dcj) {
uint32 blockW = (dcj.Width() + 3) >> 2;
uint32 blockH = (dcj.Height() + 3) >> 2;
const uint32 blockSz = GetBlockSize(FasTC::eCompressionFormat_DXT5);
uint32 *outPixels = reinterpret_cast<uint32 *>(dcj.OutBuf());
uint32 outBlock[16];
memset(outBlock, 0xFF, sizeof(outBlock));
for (uint32 j = 0; j < blockH; j++) {
for (uint32 i = 0; i < blockW; i++) {
uint32 offset = (j * blockW + i) * blockSz;
DecompressDXT5Block(dcj.InBuf() + offset, outBlock);
DecompressDXT1Block(dcj.InBuf() + offset + blockSz / 2, outBlock, false);
uint32 decompWidth = std::min(4U, dcj.Width() - i * 4);
uint32 decompHeight = std::min(4U, dcj.Height() - j * 4);
for (uint32 y = 0; y < decompHeight; y++)
for (uint32 x = 0; x < decompWidth; x++) {
offset = (j * 4 + y)*dcj.Width() + ((i * 4) + x);
outPixels[offset] = outBlock[y * 4 + x];
}
}
}
}
}

View file

@ -1,687 +0,0 @@
// stb_dxt.h - v1.06 - DXT1/DXT5 compressor - public domain
// original by fabian "ryg" giesen - ported to C by stb
// use '#define STB_DXT_IMPLEMENTATION' before including to create the implementation
//
// USAGE:
// call stb_compress_dxt_block() for every block (you must pad)
// source should be a 4x4 block of RGBA data in row-major order;
// A is ignored if you specify alpha=0; you can turn on dithering
// and "high quality" using mode.
//
// version history:
// v1.06 - (stb) fix to known-broken 1.05
// v1.05 - (stb) support bc5/3dc (Arvids Kokins), use extern "C" in C++ (Pavel Krajcevski)
// v1.04 - (ryg) default to no rounding bias for lerped colors (as per S3TC/DX10 spec);
// single color match fix (allow for inexact color interpolation);
// optimal DXT5 index finder; "high quality" mode that runs multiple refinement steps.
// v1.03 - (stb) endianness support
// v1.02 - (stb) fix alpha encoding bug
// v1.01 - (stb) fix bug converting to RGB that messed up quality, thanks ryg & cbloom
// v1.00 - (stb) first release
//
// LICENSE
//
// See end of file for license information.
#ifndef STB_INCLUDE_STB_DXT_H
#define STB_INCLUDE_STB_DXT_H
// compression mode (bitflags)
#define STB_DXT_NORMAL 0
#define STB_DXT_DITHER 1 // use dithering. dubious win. never use for normal maps and the like!
#define STB_DXT_HIGHQUAL 2 // high quality mode, does two refinement steps instead of 1. ~30-40% slower.
#ifdef __cplusplus
extern "C" {
#endif
void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src_rgba_four_bytes_per_pixel, int alpha, int mode);
void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src_rg_two_byte_per_pixel);
#ifdef __cplusplus
}
#endif
#define STB_COMPRESS_DXT_BLOCK
#ifdef STB_DXT_IMPLEMENTATION
// configuration options for DXT encoder. set them in the project/makefile or just define
// them at the top.
// STB_DXT_USE_ROUNDING_BIAS
// use a rounding bias during color interpolation. this is closer to what "ideal"
// interpolation would do but doesn't match the S3TC/DX10 spec. old versions (pre-1.03)
// implicitly had this turned on.
//
// in case you're targeting a specific type of hardware (e.g. console programmers):
// NVidia and Intel GPUs (as of 2010) as well as DX9 ref use DXT decoders that are closer
// to STB_DXT_USE_ROUNDING_BIAS. AMD/ATI, S3 and DX10 ref are closer to rounding with no bias.
// you also see "(a*5 + b*3) / 8" on some old GPU designs.
// #define STB_DXT_USE_ROUNDING_BIAS
#include <stdlib.h>
#include <math.h>
#include <string.h> // memset
static unsigned char stb__Expand5[32];
static unsigned char stb__Expand6[64];
static unsigned char stb__OMatch5[256][2];
static unsigned char stb__OMatch6[256][2];
static unsigned char stb__QuantRBTab[256+16];
static unsigned char stb__QuantGTab[256+16];
static int stb__Mul8Bit(int a, int b)
{
int t = a*b + 128;
return (t + (t >> 8)) >> 8;
}
static void stb__From16Bit(unsigned char *out, unsigned short v)
{
int rv = (v & 0xf800) >> 11;
int gv = (v & 0x07e0) >> 5;
int bv = (v & 0x001f) >> 0;
out[0] = stb__Expand5[rv];
out[1] = stb__Expand6[gv];
out[2] = stb__Expand5[bv];
out[3] = 0;
}
static unsigned short stb__As16Bit(int r, int g, int b)
{
return (stb__Mul8Bit(r,31) << 11) + (stb__Mul8Bit(g,63) << 5) + stb__Mul8Bit(b,31);
}
// linear interpolation at 1/3 point between a and b, using desired rounding type
static int stb__Lerp13(int a, int b)
{
#ifdef STB_DXT_USE_ROUNDING_BIAS
// with rounding bias
return a + stb__Mul8Bit(b-a, 0x55);
#else
// without rounding bias
// replace "/ 3" by "* 0xaaab) >> 17" if your compiler sucks or you really need every ounce of speed.
return (2*a + b) / 3;
#endif
}
// lerp RGB color
static void stb__Lerp13RGB(unsigned char *out, unsigned char *p1, unsigned char *p2)
{
out[0] = stb__Lerp13(p1[0], p2[0]);
out[1] = stb__Lerp13(p1[1], p2[1]);
out[2] = stb__Lerp13(p1[2], p2[2]);
}
/****************************************************************************/
// compute table to reproduce constant colors as accurately as possible
static void stb__PrepareOptTable(unsigned char *Table,const unsigned char *expand,int size)
{
int i,mn,mx;
for (i=0;i<256;i++) {
int bestErr = 256;
for (mn=0;mn<size;mn++) {
for (mx=0;mx<size;mx++) {
int mine = expand[mn];
int maxe = expand[mx];
int err = abs(stb__Lerp13(maxe, mine) - i);
// DX10 spec says that interpolation must be within 3% of "correct" result,
// add this as error term. (normally we'd expect a random distribution of
// +-1.5% error, but nowhere in the spec does it say that the error has to be
// unbiased - better safe than sorry).
err += abs(maxe - mine) * 3 / 100;
if(err < bestErr)
{
Table[i*2+0] = mx;
Table[i*2+1] = mn;
bestErr = err;
}
}
}
}
}
static void stb__EvalColors(unsigned char *color,unsigned short c0,unsigned short c1)
{
stb__From16Bit(color+ 0, c0);
stb__From16Bit(color+ 4, c1);
stb__Lerp13RGB(color+ 8, color+0, color+4);
stb__Lerp13RGB(color+12, color+4, color+0);
}
// Block dithering function. Simply dithers a block to 565 RGB.
// (Floyd-Steinberg)
static void stb__DitherBlock(unsigned char *dest, unsigned char *block)
{
int err[8],*ep1 = err,*ep2 = err+4, *et;
int ch,y;
// process channels seperately
for (ch=0; ch<3; ++ch) {
unsigned char *bp = block+ch, *dp = dest+ch;
unsigned char *quant = (ch == 1) ? stb__QuantGTab+8 : stb__QuantRBTab+8;
memset(err, 0, sizeof(err));
for(y=0; y<4; ++y) {
dp[ 0] = quant[bp[ 0] + ((3*ep2[1] + 5*ep2[0]) >> 4)];
ep1[0] = bp[ 0] - dp[ 0];
dp[ 4] = quant[bp[ 4] + ((7*ep1[0] + 3*ep2[2] + 5*ep2[1] + ep2[0]) >> 4)];
ep1[1] = bp[ 4] - dp[ 4];
dp[ 8] = quant[bp[ 8] + ((7*ep1[1] + 3*ep2[3] + 5*ep2[2] + ep2[1]) >> 4)];
ep1[2] = bp[ 8] - dp[ 8];
dp[12] = quant[bp[12] + ((7*ep1[2] + 5*ep2[3] + ep2[2]) >> 4)];
ep1[3] = bp[12] - dp[12];
bp += 16;
dp += 16;
et = ep1, ep1 = ep2, ep2 = et; // swap
}
}
}
// The color matching function
static unsigned int stb__MatchColorsBlock(unsigned char *block, unsigned char *color,int dither)
{
unsigned int mask = 0;
int dirr = color[0*4+0] - color[1*4+0];
int dirg = color[0*4+1] - color[1*4+1];
int dirb = color[0*4+2] - color[1*4+2];
int dots[16];
int stops[4];
int i;
int c0Point, halfPoint, c3Point;
for(i=0;i<16;i++)
dots[i] = block[i*4+0]*dirr + block[i*4+1]*dirg + block[i*4+2]*dirb;
for(i=0;i<4;i++)
stops[i] = color[i*4+0]*dirr + color[i*4+1]*dirg + color[i*4+2]*dirb;
// think of the colors as arranged on a line; project point onto that line, then choose
// next color out of available ones. we compute the crossover points for "best color in top
// half"/"best in bottom half" and then the same inside that subinterval.
//
// relying on this 1d approximation isn't always optimal in terms of euclidean distance,
// but it's very close and a lot faster.
// http://cbloomrants.blogspot.com/2008/12/12-08-08-dxtc-summary.html
c0Point = (stops[1] + stops[3]) >> 1;
halfPoint = (stops[3] + stops[2]) >> 1;
c3Point = (stops[2] + stops[0]) >> 1;
if(!dither) {
// the version without dithering is straightforward
for (i=15;i>=0;i--) {
int dot = dots[i];
mask <<= 2;
if(dot < halfPoint)
mask |= (dot < c0Point) ? 1 : 3;
else
mask |= (dot < c3Point) ? 2 : 0;
}
} else {
// with floyd-steinberg dithering
int err[8],*ep1 = err,*ep2 = err+4;
int *dp = dots, y;
c0Point <<= 4;
halfPoint <<= 4;
c3Point <<= 4;
for(i=0;i<8;i++)
err[i] = 0;
for(y=0;y<4;y++)
{
int dot,lmask,step;
dot = (dp[0] << 4) + (3*ep2[1] + 5*ep2[0]);
if(dot < halfPoint)
step = (dot < c0Point) ? 1 : 3;
else
step = (dot < c3Point) ? 2 : 0;
ep1[0] = dp[0] - stops[step];
lmask = step;
dot = (dp[1] << 4) + (7*ep1[0] + 3*ep2[2] + 5*ep2[1] + ep2[0]);
if(dot < halfPoint)
step = (dot < c0Point) ? 1 : 3;
else
step = (dot < c3Point) ? 2 : 0;
ep1[1] = dp[1] - stops[step];
lmask |= step<<2;
dot = (dp[2] << 4) + (7*ep1[1] + 3*ep2[3] + 5*ep2[2] + ep2[1]);
if(dot < halfPoint)
step = (dot < c0Point) ? 1 : 3;
else
step = (dot < c3Point) ? 2 : 0;
ep1[2] = dp[2] - stops[step];
lmask |= step<<4;
dot = (dp[3] << 4) + (7*ep1[2] + 5*ep2[3] + ep2[2]);
if(dot < halfPoint)
step = (dot < c0Point) ? 1 : 3;
else
step = (dot < c3Point) ? 2 : 0;
ep1[3] = dp[3] - stops[step];
lmask |= step<<6;
dp += 4;
mask |= lmask << (y*8);
{ int *et = ep1; ep1 = ep2; ep2 = et; } // swap
}
}
return mask;
}
// The color optimization function. (Clever code, part 1)
static void stb__OptimizeColorsBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16)
{
int mind = 0x7fffffff,maxd = -0x7fffffff;
unsigned char *minp, *maxp;
double magn;
int v_r,v_g,v_b;
static const int nIterPower = 4;
float covf[6],vfr,vfg,vfb;
// determine color distribution
int cov[6];
int mu[3],min[3],max[3];
int ch,i,iter;
for(ch=0;ch<3;ch++)
{
const unsigned char *bp = ((const unsigned char *) block) + ch;
int muv,minv,maxv;
muv = minv = maxv = bp[0];
for(i=4;i<64;i+=4)
{
muv += bp[i];
if (bp[i] < minv) minv = bp[i];
else if (bp[i] > maxv) maxv = bp[i];
}
mu[ch] = (muv + 8) >> 4;
min[ch] = minv;
max[ch] = maxv;
}
// determine covariance matrix
for (i=0;i<6;i++)
cov[i] = 0;
for (i=0;i<16;i++)
{
int r = block[i*4+0] - mu[0];
int g = block[i*4+1] - mu[1];
int b = block[i*4+2] - mu[2];
cov[0] += r*r;
cov[1] += r*g;
cov[2] += r*b;
cov[3] += g*g;
cov[4] += g*b;
cov[5] += b*b;
}
// convert covariance matrix to float, find principal axis via power iter
for(i=0;i<6;i++)
covf[i] = cov[i] / 255.0f;
vfr = (float) (max[0] - min[0]);
vfg = (float) (max[1] - min[1]);
vfb = (float) (max[2] - min[2]);
for(iter=0;iter<nIterPower;iter++)
{
float r = vfr*covf[0] + vfg*covf[1] + vfb*covf[2];
float g = vfr*covf[1] + vfg*covf[3] + vfb*covf[4];
float b = vfr*covf[2] + vfg*covf[4] + vfb*covf[5];
vfr = r;
vfg = g;
vfb = b;
}
magn = fabs(vfr);
if (fabs(vfg) > magn) magn = fabs(vfg);
if (fabs(vfb) > magn) magn = fabs(vfb);
if(magn < 4.0f) { // too small, default to luminance
v_r = 299; // JPEG YCbCr luma coefs, scaled by 1000.
v_g = 587;
v_b = 114;
} else {
magn = 512.0 / magn;
v_r = (int) (vfr * magn);
v_g = (int) (vfg * magn);
v_b = (int) (vfb * magn);
}
// Pick colors at extreme points
for(i=0;i<16;i++)
{
int dot = block[i*4+0]*v_r + block[i*4+1]*v_g + block[i*4+2]*v_b;
if (dot < mind) {
mind = dot;
minp = block+i*4;
}
if (dot > maxd) {
maxd = dot;
maxp = block+i*4;
}
}
*pmax16 = stb__As16Bit(maxp[0],maxp[1],maxp[2]);
*pmin16 = stb__As16Bit(minp[0],minp[1],minp[2]);
}
static int stb__sclamp(float y, int p0, int p1)
{
int x = (int) y;
if (x < p0) return p0;
if (x > p1) return p1;
return x;
}
// The refinement function. (Clever code, part 2)
// Tries to optimize colors to suit block contents better.
// (By solving a least squares system via normal equations+Cramer's rule)
static int stb__RefineBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16, unsigned int mask)
{
static const int w1Tab[4] = { 3,0,2,1 };
static const int prods[4] = { 0x090000,0x000900,0x040102,0x010402 };
// ^some magic to save a lot of multiplies in the accumulating loop...
// (precomputed products of weights for least squares system, accumulated inside one 32-bit register)
float frb,fg;
unsigned short oldMin, oldMax, min16, max16;
int i, akku = 0, xx,xy,yy;
int At1_r,At1_g,At1_b;
int At2_r,At2_g,At2_b;
unsigned int cm = mask;
oldMin = *pmin16;
oldMax = *pmax16;
if((mask ^ (mask<<2)) < 4) // all pixels have the same index?
{
// yes, linear system would be singular; solve using optimal
// single-color match on average color
int r = 8, g = 8, b = 8;
for (i=0;i<16;++i) {
r += block[i*4+0];
g += block[i*4+1];
b += block[i*4+2];
}
r >>= 4; g >>= 4; b >>= 4;
max16 = (stb__OMatch5[r][0]<<11) | (stb__OMatch6[g][0]<<5) | stb__OMatch5[b][0];
min16 = (stb__OMatch5[r][1]<<11) | (stb__OMatch6[g][1]<<5) | stb__OMatch5[b][1];
} else {
At1_r = At1_g = At1_b = 0;
At2_r = At2_g = At2_b = 0;
for (i=0;i<16;++i,cm>>=2) {
int step = cm&3;
int w1 = w1Tab[step];
int r = block[i*4+0];
int g = block[i*4+1];
int b = block[i*4+2];
akku += prods[step];
At1_r += w1*r;
At1_g += w1*g;
At1_b += w1*b;
At2_r += r;
At2_g += g;
At2_b += b;
}
At2_r = 3*At2_r - At1_r;
At2_g = 3*At2_g - At1_g;
At2_b = 3*At2_b - At1_b;
// extract solutions and decide solvability
xx = akku >> 16;
yy = (akku >> 8) & 0xff;
xy = (akku >> 0) & 0xff;
frb = 3.0f * 31.0f / 255.0f / (xx*yy - xy*xy);
fg = frb * 63.0f / 31.0f;
// solve.
max16 = stb__sclamp((At1_r*yy - At2_r*xy)*frb+0.5f,0,31) << 11;
max16 |= stb__sclamp((At1_g*yy - At2_g*xy)*fg +0.5f,0,63) << 5;
max16 |= stb__sclamp((At1_b*yy - At2_b*xy)*frb+0.5f,0,31) << 0;
min16 = stb__sclamp((At2_r*xx - At1_r*xy)*frb+0.5f,0,31) << 11;
min16 |= stb__sclamp((At2_g*xx - At1_g*xy)*fg +0.5f,0,63) << 5;
min16 |= stb__sclamp((At2_b*xx - At1_b*xy)*frb+0.5f,0,31) << 0;
}
*pmin16 = min16;
*pmax16 = max16;
return oldMin != min16 || oldMax != max16;
}
// Color block compression
static void stb__CompressColorBlock(unsigned char *dest, unsigned char *block, int mode)
{
unsigned int mask;
int i;
int dither;
int refinecount;
unsigned short max16, min16;
unsigned char dblock[16*4],color[4*4];
dither = mode & STB_DXT_DITHER;
refinecount = (mode & STB_DXT_HIGHQUAL) ? 2 : 1;
// check if block is constant
for (i=1;i<16;i++)
if (((unsigned int *) block)[i] != ((unsigned int *) block)[0])
break;
if(i == 16) { // constant color
int r = block[0], g = block[1], b = block[2];
mask = 0xaaaaaaaa;
max16 = (stb__OMatch5[r][0]<<11) | (stb__OMatch6[g][0]<<5) | stb__OMatch5[b][0];
min16 = (stb__OMatch5[r][1]<<11) | (stb__OMatch6[g][1]<<5) | stb__OMatch5[b][1];
} else {
// first step: compute dithered version for PCA if desired
if(dither)
stb__DitherBlock(dblock,block);
// second step: pca+map along principal axis
stb__OptimizeColorsBlock(dither ? dblock : block,&max16,&min16);
if (max16 != min16) {
stb__EvalColors(color,max16,min16);
mask = stb__MatchColorsBlock(block,color,dither);
} else
mask = 0;
// third step: refine (multiple times if requested)
for (i=0;i<refinecount;i++) {
unsigned int lastmask = mask;
if (stb__RefineBlock(dither ? dblock : block,&max16,&min16,mask)) {
if (max16 != min16) {
stb__EvalColors(color,max16,min16);
mask = stb__MatchColorsBlock(block,color,dither);
} else {
mask = 0;
break;
}
}
if(mask == lastmask)
break;
}
}
// write the color block
if(max16 < min16)
{
unsigned short t = min16;
min16 = max16;
max16 = t;
mask ^= 0x55555555;
}
dest[0] = (unsigned char) (max16);
dest[1] = (unsigned char) (max16 >> 8);
dest[2] = (unsigned char) (min16);
dest[3] = (unsigned char) (min16 >> 8);
dest[4] = (unsigned char) (mask);
dest[5] = (unsigned char) (mask >> 8);
dest[6] = (unsigned char) (mask >> 16);
dest[7] = (unsigned char) (mask >> 24);
}
// Alpha block compression (this is easy for a change)
static void stb__CompressAlphaBlock(unsigned char *dest,unsigned char *src, int stride)
{
int i,dist,bias,dist4,dist2,bits,mask;
// find min/max color
int mn,mx;
mn = mx = src[0];
for (i=1;i<16;i++)
{
if (src[i*stride] < mn) mn = src[i*stride];
else if (src[i*stride] > mx) mx = src[i*stride];
}
// encode them
((unsigned char *)dest)[0] = mx;
((unsigned char *)dest)[1] = mn;
dest += 2;
// determine bias and emit color indices
// given the choice of mx/mn, these indices are optimal:
// http://fgiesen.wordpress.com/2009/12/15/dxt5-alpha-block-index-determination/
dist = mx-mn;
dist4 = dist*4;
dist2 = dist*2;
bias = (dist < 8) ? (dist - 1) : (dist/2 + 2);
bias -= mn * 7;
bits = 0,mask=0;
for (i=0;i<16;i++) {
int a = src[i*stride]*7 + bias;
int ind,t;
// select index. this is a "linear scale" lerp factor between 0 (val=min) and 7 (val=max).
t = (a >= dist4) ? -1 : 0; ind = t & 4; a -= dist4 & t;
t = (a >= dist2) ? -1 : 0; ind += t & 2; a -= dist2 & t;
ind += (a >= dist);
// turn linear scale into DXT index (0/1 are extremal pts)
ind = -ind & 7;
ind ^= (2 > ind);
// write index
mask |= ind << bits;
if((bits += 3) >= 8) {
*dest++ = mask;
mask >>= 8;
bits -= 8;
}
}
}
static void stb__InitDXT()
{
int i;
for(i=0;i<32;i++)
stb__Expand5[i] = (i<<3)|(i>>2);
for(i=0;i<64;i++)
stb__Expand6[i] = (i<<2)|(i>>4);
for(i=0;i<256+16;i++)
{
int v = i-8 < 0 ? 0 : i-8 > 255 ? 255 : i-8;
stb__QuantRBTab[i] = stb__Expand5[stb__Mul8Bit(v,31)];
stb__QuantGTab[i] = stb__Expand6[stb__Mul8Bit(v,63)];
}
stb__PrepareOptTable(&stb__OMatch5[0][0],stb__Expand5,32);
stb__PrepareOptTable(&stb__OMatch6[0][0],stb__Expand6,64);
}
void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode)
{
static int init=1;
if (init) {
stb__InitDXT();
init=0;
}
if (alpha) {
stb__CompressAlphaBlock(dest,(unsigned char*) src+3, 4);
dest += 8;
}
stb__CompressColorBlock(dest,(unsigned char*) src,mode);
}
void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src)
{
stb__CompressAlphaBlock(dest,(unsigned char*) src,2);
stb__CompressAlphaBlock(dest + 8,(unsigned char*) src+1,2);
}
#endif // STB_DXT_IMPLEMENTATION
#endif // STB_INCLUDE_STB_DXT_H
/*
------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------
*/

View file

@ -1,49 +0,0 @@
# Copyright 2016 The University of North Carolina at Chapel Hill
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Please send all BUG REPORTS to <pavel@cs.unc.edu>.
# <http://gamma.cs.unc.edu/FasTC/>
SET( LIBRARY_HEADERS
"include/FasTC/ETCCompressor.h"
)
SET( HEADERS
${LIBRARY_HEADERS}
src/rg_etc1.h
)
SET( SOURCES
src/Compressor.cpp
src/Decompressor.cpp
src/rg_etc1.cpp
)
INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Base/include)
INCLUDE_DIRECTORIES(${FasTC_BINARY_DIR}/Base/include)
INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/ETCEncoder/include)
INCLUDE_DIRECTORIES(${FasTC_BINARY_DIR}/ETCEncoder/include)
ADD_LIBRARY( ETCEncoder
${HEADERS}
${SOURCES}
)
INSTALL(TARGETS ETCEncoder EXPORT FasTCTargets ARCHIVE DESTINATION lib COMPONENT lib)
INSTALL(
FILES ${LIBRARY_HEADERS}
DESTINATION ${INCLUDE_INSTALL_DIR}/FasTC
COMPONENT dev)
TARGET_LINK_LIBRARIES( ETCEncoder FasTCBase )

View file

@ -1,39 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#ifndef ETCENCODER_INCLUDE_ETCCOMPRESSOR_H_
#define ETCENCODER_INCLUDE_ETCCOMPRESSOR_H_
#include "FasTC/CompressionJob.h"
#include "FasTC/TexCompTypes.h"
namespace ETCC {
// Takes a stream of compressed ETC1 data and decompresses it into R8G8B8A8
// format. The width and height must be specified in order to properly
// decompress the data.
void Decompress(const FasTC::DecompressionJob &);
// Takes a stream of uncompressed RGBA8 data and compresses it into ETC1
// version one. The width and height must be specified in order to properly
// decompress the data. This uses the library created by Rich Geldreich found here:
// https://code.google.com/p/rg-etc1
void Compress_RG(const FasTC::CompressionJob &);
} // namespace PVRTCC
#endif // ETCENCODER_INCLUDE_ETCCOMPRESSOR_H_

View file

@ -1,55 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "FasTC/ETCCompressor.h"
#include "rg_etc1.h"
#include <algorithm>
#include <cstring>
namespace ETCC {
void Compress_RG(const FasTC::CompressionJob &cj) {
rg_etc1::etc1_pack_params params;
params.m_quality = rg_etc1::cLowQuality;
rg_etc1::pack_etc1_block_init();
uint32 kBlockSz = GetBlockSize(FasTC::eCompressionFormat_ETC1);
const uint32 startBlock = cj.CoordsToBlockIdx(cj.XStart(), cj.YStart());
uint8 *outBuf = cj.OutBuf() + startBlock * kBlockSz;
const uint32 endY = std::min(cj.YEnd(), cj.Height() - 4);
uint32 startX = cj.XStart();
for(uint32 j = cj.YStart(); j <= endY; j += 4) {
const uint32 endX = j == cj.YEnd()? cj.XEnd() : cj.Width();
for(uint32 i = startX; i < endX; i += 4) {
uint32 pixels[16];
const uint32 *inPixels = reinterpret_cast<const uint32 *>(cj.InBuf());
memcpy(pixels, inPixels + j*cj.Width() + i, 4 * sizeof(uint32));
memcpy(pixels + 4, inPixels + (j+1)*cj.Width() + i, 4 * sizeof(uint32));
memcpy(pixels + 8, inPixels + (j+2)*cj.Width() + i, 4 * sizeof(uint32));
memcpy(pixels + 12, inPixels + (j+3)*cj.Width() + i, 4 * sizeof(uint32));
pack_etc1_block(outBuf, pixels, params);
outBuf += kBlockSz;
}
startX = 0;
}
}
} // namespace PVRTCC

View file

@ -1,49 +0,0 @@
// Copyright 2016 The University of North Carolina at Chapel Hill
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Please send all BUG REPORTS to <pavel@cs.unc.edu>.
// <http://gamma.cs.unc.edu/FasTC/>
#include "FasTC/ETCCompressor.h"
#include "rg_etc1.h"
#include <algorithm>
#include <cassert>
namespace ETCC {
void Decompress(const FasTC::DecompressionJob &dcj) {
uint32 blocksX = (dcj.Width() + 3) / 4;
uint32 blocksY = (dcj.Height() + 3) / 4;
for(uint32 j = 0; j < blocksY; j++) {
for(uint32 i = 0; i < blocksX; i++) {
uint32 pixels[16];
uint32 blockIdx = j*blocksX + i;
rg_etc1::unpack_etc1_block(dcj.InBuf() + blockIdx * 8, pixels);
uint32 decompWidth = std::min(4U, dcj.Width() - i * 4);
uint32 decompHeight = std::min(4U, dcj.Height() - j * 4);
for(uint32 y = 0; y < decompHeight; y++)
for(uint32 x = 0; x < decompWidth; x++) {
uint32 *out = reinterpret_cast<uint32 *>(dcj.OutBuf());
out[(j*4 + y)*dcj.Width() + (i*4 + x)] = pixels[y*4 + x];
}
}
}
}
} // namespace PVRTCC

File diff suppressed because it is too large Load diff

View file

@ -1,76 +0,0 @@
// File: rg_etc1.h - Fast, high quality ETC1 block packer/unpacker - Rich Geldreich <richgel99@gmail.com>
// Please see ZLIB license at the end of this file.
#pragma once
namespace rg_etc1
{
// Unpacks an 8-byte ETC1 compressed block to a block of 4x4 32bpp RGBA pixels.
// Returns false if the block is invalid. Invalid blocks will still be unpacked with clamping.
// This function is thread safe, and does not dynamically allocate any memory.
// If preserve_alpha is true, the alpha channel of the destination pixels will not be overwritten. Otherwise, alpha will be set to 255.
bool unpack_etc1_block(const void *pETC1_block, unsigned int* pDst_pixels_rgba, bool preserve_alpha = false);
// Quality setting = the higher the quality, the slower.
// To pack large textures, it is highly recommended to call pack_etc1_block() in parallel, on different blocks, from multiple threads (particularly when using cHighQuality).
enum etc1_quality
{
cLowQuality,
cMediumQuality,
cHighQuality,
};
struct etc1_pack_params
{
etc1_quality m_quality;
bool m_dithering;
inline etc1_pack_params()
{
clear();
}
void clear()
{
m_quality = cHighQuality;
m_dithering = false;
}
};
// Important: pack_etc1_block_init() must be called before calling pack_etc1_block().
void pack_etc1_block_init();
// Packs a 4x4 block of 32bpp RGBA pixels to an 8-byte ETC1 block.
// 32-bit RGBA pixels must always be arranged as (R,G,B,A) (R first, A last) in memory, independent of platform endianness. A should always be 255.
// Returns squared error of result.
// This function is thread safe, and does not dynamically allocate any memory.
// pack_etc1_block() does not currently support "perceptual" colorspace metrics - it primarily optimizes for RGB RMSE.
unsigned int pack_etc1_block(void* pETC1_block, const unsigned int* pSrc_pixels_rgba, etc1_pack_params& pack_params);
} // namespace rg_etc1
//------------------------------------------------------------------------------
//
// rg_etc1 uses the ZLIB license:
// http://opensource.org/licenses/Zlib
//
// Copyright (c) 2012 Rich Geldreich
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
//------------------------------------------------------------------------------

View file

@ -1,153 +0,0 @@
Changes for 1.7.0:
* New feature: death tests are supported on OpenBSD and in iOS
simulator now.
* New feature: Test::RecordProperty() can now be used outside of the
lifespan of a test method, in which case it will be attributed to
the current test case or the test program in the XML report.
* New feature (potentially breaking): --gtest_list_tests now prints
the type parameters and value parameters for each test.
* Improvement: char pointers and char arrays are now escaped properly
in failure messages.
* Improvement: failure summary in XML reports now includes file and
line information.
* Improvement: the <testsuites> XML element now has a timestamp attribute.
* Improvement: When --gtest_filter is specified, XML report now doesn't
contain information about tests that are filtered out.
* Fixed the bug where long --gtest_filter flag values are truncated in
death tests.
* Potentially breaking change: RUN_ALL_TESTS() is now implemented as a
function instead of a macro in order to work better with Clang.
* Compatibility fixes with C++ 11 and various platforms.
* Bug/warning fixes.
Changes for 1.6.0:
* New feature: ADD_FAILURE_AT() for reporting a test failure at the
given source location -- useful for writing testing utilities.
* New feature: the universal value printer is moved from Google Mock
to Google Test.
* New feature: type parameters and value parameters are reported in
the XML report now.
* A gtest_disable_pthreads CMake option.
* Colored output works in GNU Screen sessions now.
* Parameters of value-parameterized tests are now printed in the
textual output.
* Failures from ad hoc test assertions run before RUN_ALL_TESTS() are
now correctly reported.
* Arguments of ASSERT_XY and EXPECT_XY no longer need to support << to
ostream.
* More complete handling of exceptions.
* GTEST_ASSERT_XY can be used instead of ASSERT_XY in case the latter
name is already used by another library.
* --gtest_catch_exceptions is now true by default, allowing a test
program to continue after an exception is thrown.
* Value-parameterized test fixtures can now derive from Test and
WithParamInterface<T> separately, easing conversion of legacy tests.
* Death test messages are clearly marked to make them more
distinguishable from other messages.
* Compatibility fixes for Android, Google Native Client, MinGW, HP UX,
PowerPC, Lucid autotools, libCStd, Sun C++, Borland C++ Builder (Code Gear),
IBM XL C++ (Visual Age C++), and C++0x.
* Bug fixes and implementation clean-ups.
* Potentially incompatible changes: disables the harmful 'make install'
command in autotools.
Changes for 1.5.0:
* New feature: assertions can be safely called in multiple threads
where the pthreads library is available.
* New feature: predicates used inside EXPECT_TRUE() and friends
can now generate custom failure messages.
* New feature: Google Test can now be compiled as a DLL.
* New feature: fused source files are included.
* New feature: prints help when encountering unrecognized Google Test flags.
* Experimental feature: CMake build script (requires CMake 2.6.4+).
* Experimental feature: the Pump script for meta programming.
* double values streamed to an assertion are printed with enough precision
to differentiate any two different values.
* Google Test now works on Solaris and AIX.
* Build and test script improvements.
* Bug fixes and implementation clean-ups.
Potentially breaking changes:
* Stopped supporting VC++ 7.1 with exceptions disabled.
* Dropped support for 'make install'.
Changes for 1.4.0:
* New feature: the event listener API
* New feature: test shuffling
* New feature: the XML report format is closer to junitreport and can
be parsed by Hudson now.
* New feature: when a test runs under Visual Studio, its failures are
integrated in the IDE.
* New feature: /MD(d) versions of VC++ projects.
* New feature: elapsed time for the tests is printed by default.
* New feature: comes with a TR1 tuple implementation such that Boost
is no longer needed for Combine().
* New feature: EXPECT_DEATH_IF_SUPPORTED macro and friends.
* New feature: the Xcode project can now produce static gtest
libraries in addition to a framework.
* Compatibility fixes for Solaris, Cygwin, minGW, Windows Mobile,
Symbian, gcc, and C++Builder.
* Bug fixes and implementation clean-ups.
Changes for 1.3.0:
* New feature: death tests on Windows, Cygwin, and Mac.
* New feature: ability to use Google Test assertions in other testing
frameworks.
* New feature: ability to run disabled test via
--gtest_also_run_disabled_tests.
* New feature: the --help flag for printing the usage.
* New feature: access to Google Test flag values in user code.
* New feature: a script that packs Google Test into one .h and one
.cc file for easy deployment.
* New feature: support for distributing test functions to multiple
machines (requires support from the test runner).
* Bug fixes and implementation clean-ups.
Changes for 1.2.1:
* Compatibility fixes for Linux IA-64 and IBM z/OS.
* Added support for using Boost and other TR1 implementations.
* Changes to the build scripts to support upcoming release of Google C++
Mocking Framework.
* Added Makefile to the distribution package.
* Improved build instructions in README.
Changes for 1.2.0:
* New feature: value-parameterized tests.
* New feature: the ASSERT/EXPECT_(NON)FATAL_FAILURE(_ON_ALL_THREADS)
macros.
* Changed the XML report format to match JUnit/Ant's.
* Added tests to the Xcode project.
* Added scons/SConscript for building with SCons.
* Added src/gtest-all.cc for building Google Test from a single file.
* Fixed compatibility with Solaris and z/OS.
* Enabled running Python tests on systems with python 2.3 installed,
e.g. Mac OS X 10.4.
* Bug fixes.
Changes for 1.1.0:
* New feature: type-parameterized tests.
* New feature: exception assertions.
* New feature: printing elapsed time of tests.
* Improved the robustness of death tests.
* Added an Xcode project and samples.
* Adjusted the output format on Windows to be understandable by Visual Studio.
* Minor bug fixes.
Changes for 1.0.1:
* Added project files for Visual Studio 7.1.
* Fixed issues with compiling on Mac OS X.
* Fixed issues with compiling on Cygwin.
Changes for 1.0.0:
* Initial Open Source release of Google Test

View file

@ -1,250 +0,0 @@
########################################################################
# CMake build script for Google Test.
#
# To run the tests for Google Test itself on Linux, use 'make test' or
# ctest. You can select which tests to run using 'ctest -R regex'.
# For more options, run 'ctest --help'.
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to
# make it prominent in the GUI.
option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
# When other libraries are using a shared version of runtime libraries,
# Google Test also has to use one.
option(
gtest_force_shared_crt
"Use shared (DLL) run-time lib even when Google Test is built as static lib."
OFF)
option(gtest_build_tests "Build all of gtest's own tests." OFF)
option(gtest_build_samples "Build gtest's sample programs." OFF)
option(gtest_disable_pthreads "Disable uses of pthreads in gtest." OFF)
# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build().
include(cmake/hermetic_build.cmake OPTIONAL)
if (COMMAND pre_project_set_up_hermetic_build)
pre_project_set_up_hermetic_build()
endif()
########################################################################
#
# Project-wide settings
# Name of the project.
#
# CMake files in this project can refer to the root source directory
# as ${gtest_SOURCE_DIR} and to the root binary directory as
# ${gtest_BINARY_DIR}.
# Language "C" is required for find_package(Threads).
project(gtest CXX C)
cmake_minimum_required(VERSION 2.6.2)
if (COMMAND set_up_hermetic_build)
set_up_hermetic_build()
endif()
# Define helper functions and macros used by Google Test.
include(cmake/internal_utils.cmake)
config_compiler_and_linker() # Defined in internal_utils.cmake.
# Where Google Test's .h files can be found.
include_directories(
${gtest_SOURCE_DIR}/include
${gtest_SOURCE_DIR})
# Where Google Test's libraries can be found.
link_directories(${gtest_BINARY_DIR}/src)
########################################################################
#
# Defines the gtest & gtest_main libraries. User tests should link
# with one of them.
# Google Test libraries. We build them using more strict warnings than what
# are used for other targets, to ensure that gtest can be compiled by a user
# aggressive about warnings.
cxx_library(gtest "${cxx_strict}" src/gtest-all.cc)
cxx_library(gtest_main "${cxx_strict}" src/gtest_main.cc)
target_link_libraries(gtest_main gtest)
########################################################################
#
# Samples on how to link user tests with gtest or gtest_main.
#
# They are not built by default. To build them, set the
# gtest_build_samples option to ON. You can do it by running ccmake
# or specifying the -Dgtest_build_samples=ON flag when running cmake.
if (gtest_build_samples)
cxx_executable(sample1_unittest samples gtest_main samples/sample1.cc)
cxx_executable(sample2_unittest samples gtest_main samples/sample2.cc)
cxx_executable(sample3_unittest samples gtest_main)
cxx_executable(sample4_unittest samples gtest_main samples/sample4.cc)
cxx_executable(sample5_unittest samples gtest_main samples/sample1.cc)
cxx_executable(sample6_unittest samples gtest_main)
cxx_executable(sample7_unittest samples gtest_main)
cxx_executable(sample8_unittest samples gtest_main)
cxx_executable(sample9_unittest samples gtest)
cxx_executable(sample10_unittest samples gtest)
endif()
########################################################################
#
# Google Test's own tests.
#
# You can skip this section if you aren't interested in testing
# Google Test itself.
#
# The tests are not built by default. To build them, set the
# gtest_build_tests option to ON. You can do it by running ccmake
# or specifying the -Dgtest_build_tests=ON flag when running cmake.
if (gtest_build_tests)
# This must be set in the root directory for the tests to be run by
# 'make test' or ctest.
enable_testing()
############################################################
# C++ tests built with standard compiler flags.
cxx_test(gtest-death-test_test gtest_main)
cxx_test(gtest_environment_test gtest)
cxx_test(gtest-filepath_test gtest_main)
cxx_test(gtest-linked_ptr_test gtest_main)
cxx_test(gtest-listener_test gtest_main)
cxx_test(gtest_main_unittest gtest_main)
cxx_test(gtest-message_test gtest_main)
cxx_test(gtest_no_test_unittest gtest)
cxx_test(gtest-options_test gtest_main)
cxx_test(gtest-param-test_test gtest
test/gtest-param-test2_test.cc)
cxx_test(gtest-port_test gtest_main)
cxx_test(gtest_pred_impl_unittest gtest_main)
cxx_test(gtest-printers_test gtest_main)
cxx_test(gtest_prod_test gtest_main
test/production.cc)
cxx_test(gtest_repeat_test gtest)
cxx_test(gtest_sole_header_test gtest_main)
cxx_test(gtest_stress_test gtest)
cxx_test(gtest-test-part_test gtest_main)
cxx_test(gtest_throw_on_failure_ex_test gtest)
cxx_test(gtest-typed-test_test gtest_main
test/gtest-typed-test2_test.cc)
cxx_test(gtest_unittest gtest_main)
cxx_test(gtest-unittest-api_test gtest)
############################################################
# C++ tests built with non-standard compiler flags.
# MSVC 7.1 does not support STL with exceptions disabled.
if (NOT MSVC OR MSVC_VERSION GREATER 1310)
cxx_library(gtest_no_exception "${cxx_no_exception}"
src/gtest-all.cc)
cxx_library(gtest_main_no_exception "${cxx_no_exception}"
src/gtest-all.cc src/gtest_main.cc)
endif()
cxx_library(gtest_main_no_rtti "${cxx_no_rtti}"
src/gtest-all.cc src/gtest_main.cc)
cxx_test_with_flags(gtest-death-test_ex_nocatch_test
"${cxx_exception} -DGTEST_ENABLE_CATCH_EXCEPTIONS_=0"
gtest test/gtest-death-test_ex_test.cc)
cxx_test_with_flags(gtest-death-test_ex_catch_test
"${cxx_exception} -DGTEST_ENABLE_CATCH_EXCEPTIONS_=1"
gtest test/gtest-death-test_ex_test.cc)
cxx_test_with_flags(gtest_no_rtti_unittest "${cxx_no_rtti}"
gtest_main_no_rtti test/gtest_unittest.cc)
cxx_shared_library(gtest_dll "${cxx_default}"
src/gtest-all.cc src/gtest_main.cc)
cxx_executable_with_flags(gtest_dll_test_ "${cxx_default}"
gtest_dll test/gtest_all_test.cc)
set_target_properties(gtest_dll_test_
PROPERTIES
COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
if (NOT MSVC OR NOT MSVC_VERSION EQUAL 1600)
# The C++ Standard specifies tuple_element<int, class>.
# Yet MSVC 10's <utility> declares tuple_element<size_t, class>.
# That declaration conflicts with our own standard-conforming
# tuple implementation. Therefore using our own tuple with
# MSVC 10 doesn't compile.
cxx_library(gtest_main_use_own_tuple "${cxx_use_own_tuple}"
src/gtest-all.cc src/gtest_main.cc)
cxx_test_with_flags(gtest-tuple_test "${cxx_use_own_tuple}"
gtest_main_use_own_tuple test/gtest-tuple_test.cc)
cxx_test_with_flags(gtest_use_own_tuple_test "${cxx_use_own_tuple}"
gtest_main_use_own_tuple
test/gtest-param-test_test.cc test/gtest-param-test2_test.cc)
endif()
############################################################
# Python tests.
cxx_executable(gtest_break_on_failure_unittest_ test gtest)
py_test(gtest_break_on_failure_unittest)
# MSVC 7.1 does not support STL with exceptions disabled.
if (NOT MSVC OR MSVC_VERSION GREATER 1310)
cxx_executable_with_flags(
gtest_catch_exceptions_no_ex_test_
"${cxx_no_exception}"
gtest_main_no_exception
test/gtest_catch_exceptions_test_.cc)
endif()
cxx_executable_with_flags(
gtest_catch_exceptions_ex_test_
"${cxx_exception}"
gtest_main
test/gtest_catch_exceptions_test_.cc)
py_test(gtest_catch_exceptions_test)
cxx_executable(gtest_color_test_ test gtest)
py_test(gtest_color_test)
cxx_executable(gtest_env_var_test_ test gtest)
py_test(gtest_env_var_test)
cxx_executable(gtest_filter_unittest_ test gtest)
py_test(gtest_filter_unittest)
cxx_executable(gtest_help_test_ test gtest_main)
py_test(gtest_help_test)
cxx_executable(gtest_list_tests_unittest_ test gtest)
py_test(gtest_list_tests_unittest)
cxx_executable(gtest_output_test_ test gtest)
py_test(gtest_output_test)
cxx_executable(gtest_shuffle_test_ test gtest)
py_test(gtest_shuffle_test)
# MSVC 7.1 does not support STL with exceptions disabled.
if (NOT MSVC OR MSVC_VERSION GREATER 1310)
cxx_executable(gtest_throw_on_failure_test_ test gtest_no_exception)
set_target_properties(gtest_throw_on_failure_test_
PROPERTIES
COMPILE_FLAGS "${cxx_no_exception}")
py_test(gtest_throw_on_failure_test)
endif()
cxx_executable(gtest_uninitialized_test_ test gtest)
py_test(gtest_uninitialized_test)
cxx_executable(gtest_xml_outfile1_test_ test gtest_main)
cxx_executable(gtest_xml_outfile2_test_ test gtest_main)
py_test(gtest_xml_outfiles_test)
cxx_executable(gtest_xml_output_unittest_ test gtest)
py_test(gtest_xml_output_unittest)
endif()

View file

@ -1,37 +0,0 @@
# This file contains a list of people who've made non-trivial
# contribution to the Google C++ Testing Framework project. People
# who commit code to the project are encouraged to add their names
# here. Please keep the list sorted by first names.
Ajay Joshi <jaj@google.com>
Balázs Dán <balazs.dan@gmail.com>
Bharat Mediratta <bharat@menalto.com>
Chandler Carruth <chandlerc@google.com>
Chris Prince <cprince@google.com>
Chris Taylor <taylorc@google.com>
Dan Egnor <egnor@google.com>
Eric Roman <eroman@chromium.org>
Hady Zalek <hady.zalek@gmail.com>
Jeffrey Yasskin <jyasskin@google.com>
Jói Sigurðsson <joi@google.com>
Keir Mierle <mierle@gmail.com>
Keith Ray <keith.ray@gmail.com>
Kenton Varda <kenton@google.com>
Manuel Klimek <klimek@google.com>
Markus Heule <markus.heule@gmail.com>
Mika Raento <mikie@iki.fi>
Miklós Fazekas <mfazekas@szemafor.com>
Pasi Valminen <pasi.valminen@gmail.com>
Patrick Hanna <phanna@google.com>
Patrick Riley <pfr@google.com>
Peter Kaminski <piotrk@google.com>
Preston Jackson <preston.a.jackson@gmail.com>
Rainer Klaffenboeck <rainer.klaffenboeck@dynatrace.com>
Russ Cox <rsc@google.com>
Russ Rufer <russ@pentad.com>
Sean Mcafee <eefacm@gmail.com>
Sigurður Ásgeirsson <siggi@google.com>
Tracy Bialik <tracy@pentad.com>
Vadim Berman <vadimb@google.com>
Vlad Losev <vladl@google.com>
Zhanyong Wan <wan@google.com>

View file

@ -1,28 +0,0 @@
Copyright 2008, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,305 +0,0 @@
# Automake file
ACLOCAL_AMFLAGS = -I m4
# Nonstandard package files for distribution
EXTRA_DIST = \
CHANGES \
CONTRIBUTORS \
LICENSE \
include/gtest/gtest-param-test.h.pump \
include/gtest/internal/gtest-param-util-generated.h.pump \
include/gtest/internal/gtest-tuple.h.pump \
include/gtest/internal/gtest-type-util.h.pump \
make/Makefile \
scripts/fuse_gtest_files.py \
scripts/gen_gtest_pred_impl.py \
scripts/pump.py \
scripts/test/Makefile
# gtest source files that we don't compile directly. They are
# #included by gtest-all.cc.
GTEST_SRC = \
src/gtest-death-test.cc \
src/gtest-filepath.cc \
src/gtest-internal-inl.h \
src/gtest-port.cc \
src/gtest-printers.cc \
src/gtest-test-part.cc \
src/gtest-typed-test.cc \
src/gtest.cc
EXTRA_DIST += $(GTEST_SRC)
# Sample files that we don't compile.
EXTRA_DIST += \
samples/prime_tables.h \
samples/sample2_unittest.cc \
samples/sample3_unittest.cc \
samples/sample4_unittest.cc \
samples/sample5_unittest.cc \
samples/sample6_unittest.cc \
samples/sample7_unittest.cc \
samples/sample8_unittest.cc \
samples/sample9_unittest.cc
# C++ test files that we don't compile directly.
EXTRA_DIST += \
test/gtest-death-test_ex_test.cc \
test/gtest-death-test_test.cc \
test/gtest-filepath_test.cc \
test/gtest-linked_ptr_test.cc \
test/gtest-listener_test.cc \
test/gtest-message_test.cc \
test/gtest-options_test.cc \
test/gtest-param-test2_test.cc \
test/gtest-param-test2_test.cc \
test/gtest-param-test_test.cc \
test/gtest-param-test_test.cc \
test/gtest-param-test_test.h \
test/gtest-port_test.cc \
test/gtest-printers_test.cc \
test/gtest-test-part_test.cc \
test/gtest-tuple_test.cc \
test/gtest-typed-test2_test.cc \
test/gtest-typed-test_test.cc \
test/gtest-typed-test_test.h \
test/gtest-unittest-api_test.cc \
test/gtest_break_on_failure_unittest_.cc \
test/gtest_catch_exceptions_test_.cc \
test/gtest_color_test_.cc \
test/gtest_env_var_test_.cc \
test/gtest_environment_test.cc \
test/gtest_filter_unittest_.cc \
test/gtest_help_test_.cc \
test/gtest_list_tests_unittest_.cc \
test/gtest_main_unittest.cc \
test/gtest_no_test_unittest.cc \
test/gtest_output_test_.cc \
test/gtest_pred_impl_unittest.cc \
test/gtest_prod_test.cc \
test/gtest_repeat_test.cc \
test/gtest_shuffle_test_.cc \
test/gtest_sole_header_test.cc \
test/gtest_stress_test.cc \
test/gtest_throw_on_failure_ex_test.cc \
test/gtest_throw_on_failure_test_.cc \
test/gtest_uninitialized_test_.cc \
test/gtest_unittest.cc \
test/gtest_unittest.cc \
test/gtest_xml_outfile1_test_.cc \
test/gtest_xml_outfile2_test_.cc \
test/gtest_xml_output_unittest_.cc \
test/production.cc \
test/production.h
# Python tests that we don't run.
EXTRA_DIST += \
test/gtest_break_on_failure_unittest.py \
test/gtest_catch_exceptions_test.py \
test/gtest_color_test.py \
test/gtest_env_var_test.py \
test/gtest_filter_unittest.py \
test/gtest_help_test.py \
test/gtest_list_tests_unittest.py \
test/gtest_output_test.py \
test/gtest_output_test_golden_lin.txt \
test/gtest_shuffle_test.py \
test/gtest_test_utils.py \
test/gtest_throw_on_failure_test.py \
test/gtest_uninitialized_test.py \
test/gtest_xml_outfiles_test.py \
test/gtest_xml_output_unittest.py \
test/gtest_xml_test_utils.py
# CMake script
EXTRA_DIST += \
CMakeLists.txt \
cmake/internal_utils.cmake
# MSVC project files
EXTRA_DIST += \
msvc/gtest-md.sln \
msvc/gtest-md.vcproj \
msvc/gtest.sln \
msvc/gtest.vcproj \
msvc/gtest_main-md.vcproj \
msvc/gtest_main.vcproj \
msvc/gtest_prod_test-md.vcproj \
msvc/gtest_prod_test.vcproj \
msvc/gtest_unittest-md.vcproj \
msvc/gtest_unittest.vcproj
# xcode project files
EXTRA_DIST += \
xcode/Config/DebugProject.xcconfig \
xcode/Config/FrameworkTarget.xcconfig \
xcode/Config/General.xcconfig \
xcode/Config/ReleaseProject.xcconfig \
xcode/Config/StaticLibraryTarget.xcconfig \
xcode/Config/TestTarget.xcconfig \
xcode/Resources/Info.plist \
xcode/Scripts/runtests.sh \
xcode/Scripts/versiongenerate.py \
xcode/gtest.xcodeproj/project.pbxproj
# xcode sample files
EXTRA_DIST += \
xcode/Samples/FrameworkSample/Info.plist \
xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj \
xcode/Samples/FrameworkSample/runtests.sh \
xcode/Samples/FrameworkSample/widget.cc \
xcode/Samples/FrameworkSample/widget.h \
xcode/Samples/FrameworkSample/widget_test.cc
# C++Builder project files
EXTRA_DIST += \
codegear/gtest.cbproj \
codegear/gtest.groupproj \
codegear/gtest_all.cc \
codegear/gtest_link.cc \
codegear/gtest_main.cbproj \
codegear/gtest_unittest.cbproj
# Distribute and install M4 macro
m4datadir = $(datadir)/aclocal
m4data_DATA = m4/gtest.m4
EXTRA_DIST += $(m4data_DATA)
# We define the global AM_CPPFLAGS as everything we compile includes from these
# directories.
AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/include
# Modifies compiler and linker flags for pthreads compatibility.
if HAVE_PTHREADS
AM_CXXFLAGS = @PTHREAD_CFLAGS@ -DGTEST_HAS_PTHREAD=1
AM_LIBS = @PTHREAD_LIBS@
else
AM_CXXFLAGS = -DGTEST_HAS_PTHREAD=0
endif
# Build rules for libraries.
lib_LTLIBRARIES = lib/libgtest.la lib/libgtest_main.la
lib_libgtest_la_SOURCES = src/gtest-all.cc
pkginclude_HEADERS = \
include/gtest/gtest-death-test.h \
include/gtest/gtest-message.h \
include/gtest/gtest-param-test.h \
include/gtest/gtest-printers.h \
include/gtest/gtest-spi.h \
include/gtest/gtest-test-part.h \
include/gtest/gtest-typed-test.h \
include/gtest/gtest.h \
include/gtest/gtest_pred_impl.h \
include/gtest/gtest_prod.h
pkginclude_internaldir = $(pkgincludedir)/internal
pkginclude_internal_HEADERS = \
include/gtest/internal/gtest-death-test-internal.h \
include/gtest/internal/gtest-filepath.h \
include/gtest/internal/gtest-internal.h \
include/gtest/internal/gtest-linked_ptr.h \
include/gtest/internal/gtest-param-util-generated.h \
include/gtest/internal/gtest-param-util.h \
include/gtest/internal/gtest-port.h \
include/gtest/internal/gtest-string.h \
include/gtest/internal/gtest-tuple.h \
include/gtest/internal/gtest-type-util.h
lib_libgtest_main_la_SOURCES = src/gtest_main.cc
lib_libgtest_main_la_LIBADD = lib/libgtest.la
# Bulid rules for samples and tests. Automake's naming for some of
# these variables isn't terribly obvious, so this is a brief
# reference:
#
# TESTS -- Programs run automatically by "make check"
# check_PROGRAMS -- Programs built by "make check" but not necessarily run
noinst_LTLIBRARIES = samples/libsamples.la
samples_libsamples_la_SOURCES = \
samples/sample1.cc \
samples/sample1.h \
samples/sample2.cc \
samples/sample2.h \
samples/sample3-inl.h \
samples/sample4.cc \
samples/sample4.h
TESTS=
TESTS_ENVIRONMENT = GTEST_SOURCE_DIR="$(srcdir)/test" \
GTEST_BUILD_DIR="$(top_builddir)/test"
check_PROGRAMS=
# A simple sample on using gtest.
TESTS += samples/sample1_unittest
check_PROGRAMS += samples/sample1_unittest
samples_sample1_unittest_SOURCES = samples/sample1_unittest.cc
samples_sample1_unittest_LDADD = lib/libgtest_main.la \
lib/libgtest.la \
samples/libsamples.la
# Another sample. It also verifies that libgtest works.
TESTS += samples/sample10_unittest
check_PROGRAMS += samples/sample10_unittest
samples_sample10_unittest_SOURCES = samples/sample10_unittest.cc
samples_sample10_unittest_LDADD = lib/libgtest.la
# This tests most constructs of gtest and verifies that libgtest_main
# and libgtest work.
TESTS += test/gtest_all_test
check_PROGRAMS += test/gtest_all_test
test_gtest_all_test_SOURCES = test/gtest_all_test.cc
test_gtest_all_test_LDADD = lib/libgtest_main.la \
lib/libgtest.la
# Tests that fused gtest files compile and work.
FUSED_GTEST_SRC = \
fused-src/gtest/gtest-all.cc \
fused-src/gtest/gtest.h \
fused-src/gtest/gtest_main.cc
if HAVE_PYTHON
TESTS += test/fused_gtest_test
check_PROGRAMS += test/fused_gtest_test
test_fused_gtest_test_SOURCES = $(FUSED_GTEST_SRC) \
samples/sample1.cc samples/sample1_unittest.cc
test_fused_gtest_test_CPPFLAGS = -I"$(srcdir)/fused-src"
# Build rules for putting fused Google Test files into the distribution
# package. The user can also create those files by manually running
# scripts/fuse_gtest_files.py.
$(test_fused_gtest_test_SOURCES): fused-gtest
fused-gtest: $(pkginclude_HEADERS) $(pkginclude_internal_HEADERS) \
$(GTEST_SRC) src/gtest-all.cc src/gtest_main.cc \
scripts/fuse_gtest_files.py
mkdir -p "$(srcdir)/fused-src"
chmod -R u+w "$(srcdir)/fused-src"
rm -f "$(srcdir)/fused-src/gtest/gtest-all.cc"
rm -f "$(srcdir)/fused-src/gtest/gtest.h"
"$(srcdir)/scripts/fuse_gtest_files.py" "$(srcdir)/fused-src"
cp -f "$(srcdir)/src/gtest_main.cc" "$(srcdir)/fused-src/gtest/"
maintainer-clean-local:
rm -rf "$(srcdir)/fused-src"
endif
# Death tests may produce core dumps in the build directory. In case
# this happens, clean them to keep distcleancheck happy.
CLEANFILES = core
# Disables 'make install' as installing a compiled version of Google
# Test can lead to undefined behavior due to violation of the
# One-Definition Rule.
install-exec-local:
echo "'make install' is dangerous and not supported. Instead, see README for how to integrate Google Test into your build system."
false
install-data-local:
echo "'make install' is dangerous and not supported. Instead, see README for how to integrate Google Test into your build system."
false

View file

@ -1,435 +0,0 @@
Google C++ Testing Framework
============================
http://code.google.com/p/googletest/
Overview
--------
Google's framework for writing C++ tests on a variety of platforms
(Linux, Mac OS X, Windows, Windows CE, Symbian, etc). Based on the
xUnit architecture. Supports automatic test discovery, a rich set of
assertions, user-defined assertions, death tests, fatal and non-fatal
failures, various options for running the tests, and XML test report
generation.
Please see the project page above for more information as well as the
mailing list for questions, discussions, and development. There is
also an IRC channel on OFTC (irc.oftc.net) #gtest available. Please
join us!
Requirements for End Users
--------------------------
Google Test is designed to have fairly minimal requirements to build
and use with your projects, but there are some. Currently, we support
Linux, Windows, Mac OS X, and Cygwin. We will also make our best
effort to support other platforms (e.g. Solaris, AIX, and z/OS).
However, since core members of the Google Test project have no access
to these platforms, Google Test may have outstanding issues there. If
you notice any problems on your platform, please notify
googletestframework@googlegroups.com. Patches for fixing them are
even more welcome!
### Linux Requirements ###
These are the base requirements to build and use Google Test from a source
package (as described below):
* GNU-compatible Make or gmake
* POSIX-standard shell
* POSIX(-2) Regular Expressions (regex.h)
* A C++98-standard-compliant compiler
### Windows Requirements ###
* Microsoft Visual C++ 7.1 or newer
### Cygwin Requirements ###
* Cygwin 1.5.25-14 or newer
### Mac OS X Requirements ###
* Mac OS X 10.4 Tiger or newer
* Developer Tools Installed
Also, you'll need CMake 2.6.4 or higher if you want to build the
samples using the provided CMake script, regardless of the platform.
Requirements for Contributors
-----------------------------
We welcome patches. If you plan to contribute a patch, you need to
build Google Test and its own tests from an SVN checkout (described
below), which has further requirements:
* Python version 2.3 or newer (for running some of the tests and
re-generating certain source files from templates)
* CMake 2.6.4 or newer
Getting the Source
------------------
There are two primary ways of getting Google Test's source code: you
can download a stable source release in your preferred archive format,
or directly check out the source from our Subversion (SVN) repositary.
The SVN checkout requires a few extra steps and some extra software
packages on your system, but lets you track the latest development and
make patches much more easily, so we highly encourage it.
### Source Package ###
Google Test is released in versioned source packages which can be
downloaded from the download page [1]. Several different archive
formats are provided, but the only difference is the tools used to
manipulate them, and the size of the resulting file. Download
whichever you are most comfortable with.
[1] http://code.google.com/p/googletest/downloads/list
Once the package is downloaded, expand it using whichever tools you
prefer for that type. This will result in a new directory with the
name "gtest-X.Y.Z" which contains all of the source code. Here are
some examples on Linux:
tar -xvzf gtest-X.Y.Z.tar.gz
tar -xvjf gtest-X.Y.Z.tar.bz2
unzip gtest-X.Y.Z.zip
### SVN Checkout ###
To check out the main branch (also known as the "trunk") of Google
Test, run the following Subversion command:
svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn
Setting up the Build
--------------------
To build Google Test and your tests that use it, you need to tell your
build system where to find its headers and source files. The exact
way to do it depends on which build system you use, and is usually
straightforward.
### Generic Build Instructions ###
Suppose you put Google Test in directory ${GTEST_DIR}. To build it,
create a library build target (or a project as called by Visual Studio
and Xcode) to compile
${GTEST_DIR}/src/gtest-all.cc
with ${GTEST_DIR}/include in the system header search path and ${GTEST_DIR}
in the normal header search path. Assuming a Linux-like system and gcc,
something like the following will do:
g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} \
-pthread -c ${GTEST_DIR}/src/gtest-all.cc
ar -rv libgtest.a gtest-all.o
(We need -pthread as Google Test uses threads.)
Next, you should compile your test source file with
${GTEST_DIR}/include in the system header search path, and link it
with gtest and any other necessary libraries:
g++ -isystem ${GTEST_DIR}/include -pthread path/to/your_test.cc libgtest.a \
-o your_test
As an example, the make/ directory contains a Makefile that you can
use to build Google Test on systems where GNU make is available
(e.g. Linux, Mac OS X, and Cygwin). It doesn't try to build Google
Test's own tests. Instead, it just builds the Google Test library and
a sample test. You can use it as a starting point for your own build
script.
If the default settings are correct for your environment, the
following commands should succeed:
cd ${GTEST_DIR}/make
make
./sample1_unittest
If you see errors, try to tweak the contents of make/Makefile to make
them go away. There are instructions in make/Makefile on how to do
it.
### Using CMake ###
Google Test comes with a CMake build script (CMakeLists.txt) that can
be used on a wide range of platforms ("C" stands for cross-platofrm.).
If you don't have CMake installed already, you can download it for
free from http://www.cmake.org/.
CMake works by generating native makefiles or build projects that can
be used in the compiler environment of your choice. The typical
workflow starts with:
mkdir mybuild # Create a directory to hold the build output.
cd mybuild
cmake ${GTEST_DIR} # Generate native build scripts.
If you want to build Google Test's samples, you should replace the
last command with
cmake -Dgtest_build_samples=ON ${GTEST_DIR}
If you are on a *nix system, you should now see a Makefile in the
current directory. Just type 'make' to build gtest.
If you use Windows and have Vistual Studio installed, a gtest.sln file
and several .vcproj files will be created. You can then build them
using Visual Studio.
On Mac OS X with Xcode installed, a .xcodeproj file will be generated.
### Legacy Build Scripts ###
Before settling on CMake, we have been providing hand-maintained build
projects/scripts for Visual Studio, Xcode, and Autotools. While we
continue to provide them for convenience, they are not actively
maintained any more. We highly recommend that you follow the
instructions in the previous two sections to integrate Google Test
with your existing build system.
If you still need to use the legacy build scripts, here's how:
The msvc\ folder contains two solutions with Visual C++ projects.
Open the gtest.sln or gtest-md.sln file using Visual Studio, and you
are ready to build Google Test the same way you build any Visual
Studio project. Files that have names ending with -md use DLL
versions of Microsoft runtime libraries (the /MD or the /MDd compiler
option). Files without that suffix use static versions of the runtime
libraries (the /MT or the /MTd option). Please note that one must use
the same option to compile both gtest and the test code. If you use
Visual Studio 2005 or above, we recommend the -md version as /MD is
the default for new projects in these versions of Visual Studio.
On Mac OS X, open the gtest.xcodeproj in the xcode/ folder using
Xcode. Build the "gtest" target. The universal binary framework will
end up in your selected build directory (selected in the Xcode
"Preferences..." -> "Building" pane and defaults to xcode/build).
Alternatively, at the command line, enter:
xcodebuild
This will build the "Release" configuration of gtest.framework in your
default build location. See the "xcodebuild" man page for more
information about building different configurations and building in
different locations.
If you wish to use the Google Test Xcode project with Xcode 4.x and
above, you need to either:
* update the SDK configuration options in xcode/Config/General.xconfig.
Comment options SDKROOT, MACOS_DEPLOYMENT_TARGET, and GCC_VERSION. If
you choose this route you lose the ability to target earlier versions
of MacOS X.
* Install an SDK for an earlier version. This doesn't appear to be
supported by Apple, but has been reported to work
(http://stackoverflow.com/questions/5378518).
Tweaking Google Test
--------------------
Google Test can be used in diverse environments. The default
configuration may not work (or may not work well) out of the box in
some environments. However, you can easily tweak Google Test by
defining control macros on the compiler command line. Generally,
these macros are named like GTEST_XYZ and you define them to either 1
or 0 to enable or disable a certain feature.
We list the most frequently used macros below. For a complete list,
see file include/gtest/internal/gtest-port.h.
### Choosing a TR1 Tuple Library ###
Some Google Test features require the C++ Technical Report 1 (TR1)
tuple library, which is not yet available with all compilers. The
good news is that Google Test implements a subset of TR1 tuple that's
enough for its own need, and will automatically use this when the
compiler doesn't provide TR1 tuple.
Usually you don't need to care about which tuple library Google Test
uses. However, if your project already uses TR1 tuple, you need to
tell Google Test to use the same TR1 tuple library the rest of your
project uses, or the two tuple implementations will clash. To do
that, add
-DGTEST_USE_OWN_TR1_TUPLE=0
to the compiler flags while compiling Google Test and your tests. If
you want to force Google Test to use its own tuple library, just add
-DGTEST_USE_OWN_TR1_TUPLE=1
to the compiler flags instead.
If you don't want Google Test to use tuple at all, add
-DGTEST_HAS_TR1_TUPLE=0
and all features using tuple will be disabled.
### Multi-threaded Tests ###
Google Test is thread-safe where the pthread library is available.
After #include "gtest/gtest.h", you can check the GTEST_IS_THREADSAFE
macro to see whether this is the case (yes if the macro is #defined to
1, no if it's undefined.).
If Google Test doesn't correctly detect whether pthread is available
in your environment, you can force it with
-DGTEST_HAS_PTHREAD=1
or
-DGTEST_HAS_PTHREAD=0
When Google Test uses pthread, you may need to add flags to your
compiler and/or linker to select the pthread library, or you'll get
link errors. If you use the CMake script or the deprecated Autotools
script, this is taken care of for you. If you use your own build
script, you'll need to read your compiler and linker's manual to
figure out what flags to add.
### As a Shared Library (DLL) ###
Google Test is compact, so most users can build and link it as a
static library for the simplicity. You can choose to use Google Test
as a shared library (known as a DLL on Windows) if you prefer.
To compile *gtest* as a shared library, add
-DGTEST_CREATE_SHARED_LIBRARY=1
to the compiler flags. You'll also need to tell the linker to produce
a shared library instead - consult your linker's manual for how to do
it.
To compile your *tests* that use the gtest shared library, add
-DGTEST_LINKED_AS_SHARED_LIBRARY=1
to the compiler flags.
Note: while the above steps aren't technically necessary today when
using some compilers (e.g. GCC), they may become necessary in the
future, if we decide to improve the speed of loading the library (see
http://gcc.gnu.org/wiki/Visibility for details). Therefore you are
recommended to always add the above flags when using Google Test as a
shared library. Otherwise a future release of Google Test may break
your build script.
### Avoiding Macro Name Clashes ###
In C++, macros don't obey namespaces. Therefore two libraries that
both define a macro of the same name will clash if you #include both
definitions. In case a Google Test macro clashes with another
library, you can force Google Test to rename its macro to avoid the
conflict.
Specifically, if both Google Test and some other code define macro
FOO, you can add
-DGTEST_DONT_DEFINE_FOO=1
to the compiler flags to tell Google Test to change the macro's name
from FOO to GTEST_FOO. Currently FOO can be FAIL, SUCCEED, or TEST.
For example, with -DGTEST_DONT_DEFINE_TEST=1, you'll need to write
GTEST_TEST(SomeTest, DoesThis) { ... }
instead of
TEST(SomeTest, DoesThis) { ... }
in order to define a test.
Upgrating from an Earlier Version
---------------------------------
We strive to keep Google Test releases backward compatible.
Sometimes, though, we have to make some breaking changes for the
users' long-term benefits. This section describes what you'll need to
do if you are upgrading from an earlier version of Google Test.
### Upgrading from 1.3.0 or Earlier ###
You may need to explicitly enable or disable Google Test's own TR1
tuple library. See the instructions in section "Choosing a TR1 Tuple
Library".
### Upgrading from 1.4.0 or Earlier ###
The Autotools build script (configure + make) is no longer officially
supportted. You are encouraged to migrate to your own build system or
use CMake. If you still need to use Autotools, you can find
instructions in the README file from Google Test 1.4.0.
On platforms where the pthread library is available, Google Test uses
it in order to be thread-safe. See the "Multi-threaded Tests" section
for what this means to your build script.
If you use Microsoft Visual C++ 7.1 with exceptions disabled, Google
Test will no longer compile. This should affect very few people, as a
large portion of STL (including <string>) doesn't compile in this mode
anyway. We decided to stop supporting it in order to greatly simplify
Google Test's implementation.
Developing Google Test
----------------------
This section discusses how to make your own changes to Google Test.
### Testing Google Test Itself ###
To make sure your changes work as intended and don't break existing
functionality, you'll want to compile and run Google Test's own tests.
For that you can use CMake:
mkdir mybuild
cd mybuild
cmake -Dgtest_build_tests=ON ${GTEST_DIR}
Make sure you have Python installed, as some of Google Test's tests
are written in Python. If the cmake command complains about not being
able to find Python ("Could NOT find PythonInterp (missing:
PYTHON_EXECUTABLE)"), try telling it explicitly where your Python
executable can be found:
cmake -DPYTHON_EXECUTABLE=path/to/python -Dgtest_build_tests=ON ${GTEST_DIR}
Next, you can build Google Test and all of its own tests. On *nix,
this is usually done by 'make'. To run the tests, do
make test
All tests should pass.
### Regenerating Source Files ###
Some of Google Test's source files are generated from templates (not
in the C++ sense) using a script. A template file is named FOO.pump,
where FOO is the name of the file it will generate. For example, the
file include/gtest/internal/gtest-type-util.h.pump is used to generate
gtest-type-util.h in the same directory.
Normally you don't need to worry about regenerating the source files,
unless you need to modify them. In that case, you should modify the
corresponding .pump files instead and run the pump.py Python script to
regenerate them. You can find pump.py in the scripts/ directory.
Read the Pump manual [2] for how to use it.
[2] http://code.google.com/p/googletest/wiki/PumpManual
### Contributing a Patch ###
We welcome patches. Please read the Google Test developer's guide [3]
for how you can contribute. In particular, make sure you have signed
the Contributor License Agreement, or we won't be able to accept the
patch.
[3] http://code.google.com/p/googletest/wiki/GoogleTestDevGuide
Happy testing!

View file

View file

@ -1,228 +0,0 @@
# Defines functions and macros useful for building Google Test and
# Google Mock.
#
# Note:
#
# - This file will be run twice when building Google Mock (once via
# Google Test's CMakeLists.txt, and once via Google Mock's).
# Therefore it shouldn't have any side effects other than defining
# the functions and macros.
#
# - The functions/macros defined in this file may depend on Google
# Test and Google Mock's option() definitions, and thus must be
# called *after* the options have been defined.
# Tweaks CMake's default compiler/linker settings to suit Google Test's needs.
#
# This must be a macro(), as inside a function string() can only
# update variables in the function scope.
macro(fix_default_compiler_settings_)
if (MSVC)
# For MSVC, CMake sets certain flags to defaults we want to override.
# This replacement code is taken from sample in the CMake Wiki at
# http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace.
foreach (flag_var
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if (NOT BUILD_SHARED_LIBS AND NOT gtest_force_shared_crt)
# When Google Test is built as a shared library, it should also use
# shared runtime libraries. Otherwise, it may end up with multiple
# copies of runtime library data in different modules, resulting in
# hard-to-find crashes. When it is built as a static library, it is
# preferable to use CRT as static libraries, as we don't have to rely
# on CRT DLLs being available. CMake always defaults to using shared
# CRT libraries, so we override that default here.
string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}")
endif()
# We prefer more strict warning checking for building Google Test.
# Replaces /W3 with /W4 in defaults.
string(REPLACE "/W3" "-W4" ${flag_var} "${${flag_var}}")
endforeach()
endif()
endmacro()
# Defines the compiler/linker flags used to build Google Test and
# Google Mock. You can tweak these definitions to suit your need. A
# variable's value is empty before it's explicitly assigned to.
macro(config_compiler_and_linker)
if (NOT gtest_disable_pthreads)
# Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT.
find_package(Threads)
endif()
fix_default_compiler_settings_()
if (MSVC)
# Newlines inside flags variables break CMake's NMake generator.
# TODO(vladl@google.com): Add -RTCs and -RTCu to debug builds.
set(cxx_base_flags "-GS -W4 -WX -wd4127 -wd4251 -wd4275 -nologo -J -Zi")
if (MSVC_VERSION LESS 1400)
# Suppress spurious warnings MSVC 7.1 sometimes issues.
# Forcing value to bool.
set(cxx_base_flags "${cxx_base_flags} -wd4800")
# Copy constructor and assignment operator could not be generated.
set(cxx_base_flags "${cxx_base_flags} -wd4511 -wd4512")
# Compatibility warnings not applicable to Google Test.
# Resolved overload was found by argument-dependent lookup.
set(cxx_base_flags "${cxx_base_flags} -wd4675")
endif()
set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32")
set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN")
set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1")
set(cxx_no_exception_flags "-D_HAS_EXCEPTIONS=0")
set(cxx_no_rtti_flags "-GR-")
add_definitions(-D_VARIADIC_MAX=10)
elseif (CMAKE_COMPILER_IS_GNUCXX)
set(cxx_base_flags "-Wall -Wshadow")
set(cxx_exception_flags "-fexceptions")
set(cxx_no_exception_flags "-fno-exceptions")
# Until version 4.3.2, GCC doesn't define a macro to indicate
# whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
# explicitly.
set(cxx_no_rtti_flags "-fno-rtti -DGTEST_HAS_RTTI=0")
set(cxx_strict_flags
"-Wextra -Wno-unused-parameter -Wno-missing-field-initializers")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
set(cxx_exception_flags "-features=except")
# Sun Pro doesn't provide macros to indicate whether exceptions and
# RTTI are enabled, so we define GTEST_HAS_* explicitly.
set(cxx_no_exception_flags "-features=no%except -DGTEST_HAS_EXCEPTIONS=0")
set(cxx_no_rtti_flags "-features=no%rtti -DGTEST_HAS_RTTI=0")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "VisualAge" OR
CMAKE_CXX_COMPILER_ID STREQUAL "XL")
# CMake 2.8 changes Visual Age's compiler ID to "XL".
set(cxx_exception_flags "-qeh")
set(cxx_no_exception_flags "-qnoeh")
# Until version 9.0, Visual Age doesn't define a macro to indicate
# whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
# explicitly.
set(cxx_no_rtti_flags "-qnortti -DGTEST_HAS_RTTI=0")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "HP")
set(cxx_base_flags "-AA -mt")
set(cxx_exception_flags "-DGTEST_HAS_EXCEPTIONS=1")
set(cxx_no_exception_flags "+noeh -DGTEST_HAS_EXCEPTIONS=0")
# RTTI can not be disabled in HP aCC compiler.
set(cxx_no_rtti_flags "")
endif()
if (CMAKE_USE_PTHREADS_INIT AND NOT MINGW) # The pthreads library is available and allowed.
set(cxx_base_flags "${cxx_base_flags} -DGTEST_HAS_PTHREAD=1")
else()
set(cxx_base_flags "${cxx_base_flags} -DGTEST_HAS_PTHREAD=0")
endif()
# For building gtest's own tests and samples.
set(cxx_exception "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_exception_flags}")
set(cxx_no_exception
"${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_no_exception_flags}")
set(cxx_default "${cxx_exception}")
set(cxx_no_rtti "${cxx_default} ${cxx_no_rtti_flags}")
set(cxx_use_own_tuple "${cxx_default} -DGTEST_USE_OWN_TR1_TUPLE=1")
# For building the gtest libraries.
set(cxx_strict "${cxx_default} ${cxx_strict_flags}")
endmacro()
# Defines the gtest & gtest_main libraries. User tests should link
# with one of them.
function(cxx_library_with_type name type cxx_flags)
# type can be either STATIC or SHARED to denote a static or shared library.
# ARGN refers to additional arguments after 'cxx_flags'.
add_library(${name} ${type} ${ARGN})
set_target_properties(${name}
PROPERTIES
COMPILE_FLAGS "${cxx_flags}")
if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED")
set_target_properties(${name}
PROPERTIES
COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1")
endif()
if (CMAKE_USE_PTHREADS_INIT)
target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT})
endif()
endfunction()
########################################################################
#
# Helper functions for creating build targets.
function(cxx_shared_library name cxx_flags)
cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN})
endfunction()
function(cxx_library name cxx_flags)
cxx_library_with_type(${name} "" "${cxx_flags}" ${ARGN})
endfunction()
# cxx_executable_with_flags(name cxx_flags libs srcs...)
#
# creates a named C++ executable that depends on the given libraries and
# is built from the given source files with the given compiler flags.
function(cxx_executable_with_flags name cxx_flags libs)
add_executable(${name} ${ARGN})
if (cxx_flags)
set_target_properties(${name}
PROPERTIES
COMPILE_FLAGS "${cxx_flags}")
endif()
if (BUILD_SHARED_LIBS)
set_target_properties(${name}
PROPERTIES
COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
endif()
# To support mixing linking in static and dynamic libraries, link each
# library in with an extra call to target_link_libraries.
foreach (lib "${libs}")
target_link_libraries(${name} ${lib})
endforeach()
endfunction()
# cxx_executable(name dir lib srcs...)
#
# creates a named target that depends on the given libs and is built
# from the given source files. dir/name.cc is implicitly included in
# the source file list.
function(cxx_executable name dir libs)
cxx_executable_with_flags(
${name} "${cxx_default}" "${libs}" "${dir}/${name}.cc" ${ARGN})
endfunction()
# Sets PYTHONINTERP_FOUND and PYTHON_EXECUTABLE.
find_package(PythonInterp)
# cxx_test_with_flags(name cxx_flags libs srcs...)
#
# creates a named C++ test that depends on the given libs and is built
# from the given source files with the given compiler flags.
function(cxx_test_with_flags name cxx_flags libs)
cxx_executable_with_flags(${name} "${cxx_flags}" "${libs}" ${ARGN})
add_test(${name} ${name})
endfunction()
# cxx_test(name libs srcs...)
#
# creates a named test target that depends on the given libs and is
# built from the given source files. Unlike cxx_test_with_flags,
# test/name.cc is already implicitly included in the source file list.
function(cxx_test name libs)
cxx_test_with_flags("${name}" "${cxx_default}" "${libs}"
"test/${name}.cc" ${ARGN})
endfunction()
# py_test(name)
#
# creates a Python test with the given name whose main module is in
# test/name.py. It does nothing if Python is not installed.
function(py_test name)
# We are not supporting Python tests on Linux yet as they consider
# all Linux environments to be google3 and try to use google3 features.
if (PYTHONINTERP_FOUND)
# ${CMAKE_BINARY_DIR} is known at configuration time, so we can
# directly bind it from cmake. ${CTEST_CONFIGURATION_TYPE} is known
# only at ctest runtime (by calling ctest -c <Configuration>), so
# we have to escape $ to delay variable substitution here.
add_test(${name}
${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
--build_dir=${CMAKE_CURRENT_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE})
endif()
endfunction()

View file

@ -1,138 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{bca37a72-5b07-46cf-b44e-89f8e06451a2}</ProjectGuid>
<Config Condition="'$(Config)'==''">Release</Config>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
<Base>true</Base>
<Cfg_1>true</Cfg_1>
<CfgParent>Base</CfgParent>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
<Base>true</Base>
<Cfg_2>true</Cfg_2>
<CfgParent>Base</CfgParent>
</PropertyGroup>
<PropertyGroup Condition="'$(Base)'!=''">
<BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>
<OutputExt>lib</OutputExt>
<DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>
<Defines>NO_STRICT</Defines>
<DynamicRTL>true</DynamicRTL>
<UsePackages>true</UsePackages>
<ProjectType>CppStaticLibrary</ProjectType>
<BCC_CPPCompileAlways>true</BCC_CPPCompileAlways>
<PackageImports>rtl.bpi;vcl.bpi;bcbie.bpi;vclx.bpi;vclactnband.bpi;xmlrtl.bpi;bcbsmp.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;dsnap.bpi;dsnapcon.bpi;vclib.bpi;ibxpress.bpi;adortl.bpi;dbxcds.bpi;dbexpress.bpi;DbxCommonDriver.bpi;websnap.bpi;vclie.bpi;webdsnap.bpi;inet.bpi;inetdbbde.bpi;inetdbxpress.bpi;soaprtl.bpi;Rave75VCL.bpi;teeUI.bpi;tee.bpi;teedb.bpi;IndyCore.bpi;IndySystem.bpi;IndyProtocols.bpi;IntrawebDB_90_100.bpi;Intraweb_90_100.bpi;dclZipForged11.bpi;vclZipForged11.bpi;GR32_BDS2006.bpi;GR32_DSGN_BDS2006.bpi;Jcl.bpi;JclVcl.bpi;JvCoreD11R.bpi;JvSystemD11R.bpi;JvStdCtrlsD11R.bpi;JvAppFrmD11R.bpi;JvBandsD11R.bpi;JvDBD11R.bpi;JvDlgsD11R.bpi;JvBDED11R.bpi;JvCmpD11R.bpi;JvCryptD11R.bpi;JvCtrlsD11R.bpi;JvCustomD11R.bpi;JvDockingD11R.bpi;JvDotNetCtrlsD11R.bpi;JvEDID11R.bpi;JvGlobusD11R.bpi;JvHMID11R.bpi;JvInterpreterD11R.bpi;JvJansD11R.bpi;JvManagedThreadsD11R.bpi;JvMMD11R.bpi;JvNetD11R.bpi;JvPageCompsD11R.bpi;JvPluginD11R.bpi;JvPrintPreviewD11R.bpi;JvRuntimeDesignD11R.bpi;JvTimeFrameworkD11R.bpi;JvValidatorsD11R.bpi;JvWizardD11R.bpi;JvXPCtrlsD11R.bpi;VclSmp.bpi;CExceptionExpert11.bpi</PackageImports>
<BCC_wpar>false</BCC_wpar>
<IncludePath>$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</IncludePath>
<AllPackageLibs>rtl.lib;vcl.lib</AllPackageLibs>
<TLIB_PageSize>32</TLIB_PageSize>
<ILINK_LibraryPath>$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</ILINK_LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1)'!=''">
<BCC_OptimizeForSpeed>false</BCC_OptimizeForSpeed>
<DCC_Optimize>false</DCC_Optimize>
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
<Defines>_DEBUG;$(Defines)</Defines>
<ILINK_FullDebugInfo>true</ILINK_FullDebugInfo>
<BCC_InlineFunctionExpansion>false</BCC_InlineFunctionExpansion>
<ILINK_DisableIncrementalLinking>true</ILINK_DisableIncrementalLinking>
<BCC_UseRegisterVariables>None</BCC_UseRegisterVariables>
<DCC_Define>DEBUG</DCC_Define>
<BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>
<IntermediateOutputDir>Debug</IntermediateOutputDir>
<TASM_DisplaySourceLines>true</TASM_DisplaySourceLines>
<BCC_StackFrames>true</BCC_StackFrames>
<BCC_DisableOptimizations>true</BCC_DisableOptimizations>
<ILINK_LibraryPath>$(BDS)\lib\debug;$(ILINK_LibraryPath)</ILINK_LibraryPath>
<TASM_Debugging>Full</TASM_Debugging>
<BCC_SourceDebuggingOn>true</BCC_SourceDebuggingOn>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<Defines>NDEBUG;$(Defines)</Defines>
<IntermediateOutputDir>Release</IntermediateOutputDir>
<ILINK_LibraryPath>$(BDS)\lib\release;$(ILINK_LibraryPath)</ILINK_LibraryPath>
<TASM_Debugging>None</TASM_Debugging>
</PropertyGroup>
<ProjectExtensions>
<Borland.Personality>CPlusPlusBuilder.Personality</Borland.Personality>
<Borland.ProjectType>CppStaticLibrary</Borland.ProjectType>
<BorlandProject>
<BorlandProject><CPlusPlusBuilder.Personality><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1033</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Debugging><Debugging Name="DebugSourceDirs"></Debugging></Debugging><Parameters><Parameters Name="RunParams"></Parameters><Parameters Name="Launcher"></Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="DebugCWD"></Parameters><Parameters Name="HostApplication"></Parameters><Parameters Name="RemoteHost"></Parameters><Parameters Name="RemotePath"></Parameters><Parameters Name="RemoteParams"></Parameters><Parameters Name="RemoteLauncher"></Parameters><Parameters Name="UseRemoteLauncher">False</Parameters><Parameters Name="RemoteCWD"></Parameters><Parameters Name="RemoteDebug">False</Parameters><Parameters Name="Debug Symbols Search Path"></Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><Excluded_Packages>
<Excluded_Packages Name="$(BDS)\bin\bcboffice2k100.bpl">CodeGear C++Builder Office 2000 Servers Package</Excluded_Packages>
<Excluded_Packages Name="$(BDS)\bin\bcbofficexp100.bpl">CodeGear C++Builder Office XP Servers Package</Excluded_Packages>
</Excluded_Packages><Linker><Linker Name="LibPrefix"></Linker><Linker Name="LibSuffix"></Linker><Linker Name="LibVersion"></Linker></Linker><ProjectProperties><ProjectProperties Name="AutoShowDeps">False</ProjectProperties><ProjectProperties Name="ManagePaths">True</ProjectProperties><ProjectProperties Name="VerifyPackages">True</ProjectProperties></ProjectProperties><HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Count">3</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item0">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item1">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item2">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\src;..\include</HistoryLists_hlIncludePath></HistoryLists_hlIncludePath><HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Count">1</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item0">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</HistoryLists_hlILINK_LibraryPath></HistoryLists_hlILINK_LibraryPath><HistoryLists_hlDefines><HistoryLists_hlDefines Name="Count">1</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item0">NO_STRICT</HistoryLists_hlDefines></HistoryLists_hlDefines><HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Count">1</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item0">32</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item1">16</HistoryLists_hlTLIB_PageSize></HistoryLists_hlTLIB_PageSize></CPlusPlusBuilder.Personality></BorlandProject></BorlandProject>
</ProjectExtensions>
<Import Project="$(MSBuildBinPath)\Borland.Cpp.Targets" />
<ItemGroup>
<None Include="..\include\gtest\gtest-death-test.h">
<BuildOrder>3</BuildOrder>
</None>
<None Include="..\include\gtest\gtest-message.h">
<BuildOrder>4</BuildOrder>
</None>
<None Include="..\include\gtest\gtest-param-test.h">
<BuildOrder>5</BuildOrder>
</None>
<None Include="..\include\gtest\gtest-spi.h">
<BuildOrder>6</BuildOrder>
</None>
<None Include="..\include\gtest\gtest-test-part.h">
<BuildOrder>7</BuildOrder>
</None>
<None Include="..\include\gtest\gtest-typed-test.h">
<BuildOrder>8</BuildOrder>
</None>
<None Include="..\include\gtest\gtest.h">
<BuildOrder>0</BuildOrder>
</None>
<None Include="..\include\gtest\gtest_pred_impl.h">
<BuildOrder>1</BuildOrder>
</None>
<None Include="..\include\gtest\gtest_prod.h">
<BuildOrder>2</BuildOrder>
</None>
<None Include="..\include\gtest\internal\gtest-death-test-internal.h">
<BuildOrder>9</BuildOrder>
</None>
<None Include="..\include\gtest\internal\gtest-filepath.h">
<BuildOrder>10</BuildOrder>
</None>
<None Include="..\include\gtest\internal\gtest-internal.h">
<BuildOrder>11</BuildOrder>
</None>
<None Include="..\include\gtest\internal\gtest-linked_ptr.h">
<BuildOrder>12</BuildOrder>
</None>
<None Include="..\include\gtest\internal\gtest-param-util-generated.h">
<BuildOrder>14</BuildOrder>
</None>
<None Include="..\include\gtest\internal\gtest-param-util.h">
<BuildOrder>13</BuildOrder>
</None>
<None Include="..\include\gtest\internal\gtest-port.h">
<BuildOrder>15</BuildOrder>
</None>
<None Include="..\include\gtest\internal\gtest-string.h">
<BuildOrder>16</BuildOrder>
</None>
<None Include="..\include\gtest\internal\gtest-type-util.h">
<BuildOrder>17</BuildOrder>
</None>
<CppCompile Include="gtest_all.cc">
<BuildOrder>18</BuildOrder>
</CppCompile>
<BuildConfiguration Include="Debug">
<Key>Cfg_1</Key>
</BuildConfiguration>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
</BuildConfiguration>
</ItemGroup>
</Project>

View file

@ -1,54 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{c1d923e0-6cba-4332-9b6f-3420acbf5091}</ProjectGuid>
</PropertyGroup>
<ItemGroup />
<ItemGroup>
<Projects Include="gtest.cbproj" />
<Projects Include="gtest_main.cbproj" />
<Projects Include="gtest_unittest.cbproj" />
</ItemGroup>
<ProjectExtensions>
<Borland.Personality>Default.Personality</Borland.Personality>
<Borland.ProjectType />
<BorlandProject>
<BorlandProject xmlns=""><Default.Personality></Default.Personality></BorlandProject></BorlandProject>
</ProjectExtensions>
<Target Name="gtest">
<MSBuild Projects="gtest.cbproj" Targets="" />
</Target>
<Target Name="gtest:Clean">
<MSBuild Projects="gtest.cbproj" Targets="Clean" />
</Target>
<Target Name="gtest:Make">
<MSBuild Projects="gtest.cbproj" Targets="Make" />
</Target>
<Target Name="gtest_main">
<MSBuild Projects="gtest_main.cbproj" Targets="" />
</Target>
<Target Name="gtest_main:Clean">
<MSBuild Projects="gtest_main.cbproj" Targets="Clean" />
</Target>
<Target Name="gtest_main:Make">
<MSBuild Projects="gtest_main.cbproj" Targets="Make" />
</Target>
<Target Name="gtest_unittest">
<MSBuild Projects="gtest_unittest.cbproj" Targets="" />
</Target>
<Target Name="gtest_unittest:Clean">
<MSBuild Projects="gtest_unittest.cbproj" Targets="Clean" />
</Target>
<Target Name="gtest_unittest:Make">
<MSBuild Projects="gtest_unittest.cbproj" Targets="Make" />
</Target>
<Target Name="Build">
<CallTarget Targets="gtest;gtest_main;gtest_unittest" />
</Target>
<Target Name="Clean">
<CallTarget Targets="gtest:Clean;gtest_main:Clean;gtest_unittest:Clean" />
</Target>
<Target Name="Make">
<CallTarget Targets="gtest:Make;gtest_main:Make;gtest_unittest:Make" />
</Target>
<Import Condition="Exists('$(MSBuildBinPath)\Borland.Group.Targets')" Project="$(MSBuildBinPath)\Borland.Group.Targets" />
</Project>

View file

@ -1,38 +0,0 @@
// Copyright 2009, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Josh Kelley (joshkel@gmail.com)
//
// Google C++ Testing Framework (Google Test)
//
// C++Builder's IDE cannot build a static library from files with hyphens
// in their name. See http://qc.codegear.com/wc/qcmain.aspx?d=70977 .
// This file serves as a workaround.
#include "src/gtest-all.cc"

View file

@ -1,40 +0,0 @@
// Copyright 2009, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Josh Kelley (joshkel@gmail.com)
//
// Google C++ Testing Framework (Google Test)
//
// Links gtest.lib and gtest_main.lib into the current project in C++Builder.
// This means that these libraries can't be renamed, but it's the only way to
// ensure that Debug versus Release test builds are linked against the
// appropriate Debug or Release build of the libraries.
#pragma link "gtest.lib"
#pragma link "gtest_main.lib"

View file

@ -1,82 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{bca37a72-5b07-46cf-b44e-89f8e06451a2}</ProjectGuid>
<Config Condition="'$(Config)'==''">Release</Config>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
<Base>true</Base>
<Cfg_1>true</Cfg_1>
<CfgParent>Base</CfgParent>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
<Base>true</Base>
<Cfg_2>true</Cfg_2>
<CfgParent>Base</CfgParent>
</PropertyGroup>
<PropertyGroup Condition="'$(Base)'!=''">
<BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>
<OutputExt>lib</OutputExt>
<DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>
<Defines>NO_STRICT</Defines>
<DynamicRTL>true</DynamicRTL>
<UsePackages>true</UsePackages>
<ProjectType>CppStaticLibrary</ProjectType>
<BCC_CPPCompileAlways>true</BCC_CPPCompileAlways>
<PackageImports>rtl.bpi;vcl.bpi;bcbie.bpi;vclx.bpi;vclactnband.bpi;xmlrtl.bpi;bcbsmp.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;dsnap.bpi;dsnapcon.bpi;vclib.bpi;ibxpress.bpi;adortl.bpi;dbxcds.bpi;dbexpress.bpi;DbxCommonDriver.bpi;websnap.bpi;vclie.bpi;webdsnap.bpi;inet.bpi;inetdbbde.bpi;inetdbxpress.bpi;soaprtl.bpi;Rave75VCL.bpi;teeUI.bpi;tee.bpi;teedb.bpi;IndyCore.bpi;IndySystem.bpi;IndyProtocols.bpi;IntrawebDB_90_100.bpi;Intraweb_90_100.bpi;dclZipForged11.bpi;vclZipForged11.bpi;GR32_BDS2006.bpi;GR32_DSGN_BDS2006.bpi;Jcl.bpi;JclVcl.bpi;JvCoreD11R.bpi;JvSystemD11R.bpi;JvStdCtrlsD11R.bpi;JvAppFrmD11R.bpi;JvBandsD11R.bpi;JvDBD11R.bpi;JvDlgsD11R.bpi;JvBDED11R.bpi;JvCmpD11R.bpi;JvCryptD11R.bpi;JvCtrlsD11R.bpi;JvCustomD11R.bpi;JvDockingD11R.bpi;JvDotNetCtrlsD11R.bpi;JvEDID11R.bpi;JvGlobusD11R.bpi;JvHMID11R.bpi;JvInterpreterD11R.bpi;JvJansD11R.bpi;JvManagedThreadsD11R.bpi;JvMMD11R.bpi;JvNetD11R.bpi;JvPageCompsD11R.bpi;JvPluginD11R.bpi;JvPrintPreviewD11R.bpi;JvRuntimeDesignD11R.bpi;JvTimeFrameworkD11R.bpi;JvValidatorsD11R.bpi;JvWizardD11R.bpi;JvXPCtrlsD11R.bpi;VclSmp.bpi;CExceptionExpert11.bpi</PackageImports>
<BCC_wpar>false</BCC_wpar>
<IncludePath>$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</IncludePath>
<AllPackageLibs>rtl.lib;vcl.lib</AllPackageLibs>
<TLIB_PageSize>32</TLIB_PageSize>
<ILINK_LibraryPath>$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</ILINK_LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1)'!=''">
<BCC_OptimizeForSpeed>false</BCC_OptimizeForSpeed>
<DCC_Optimize>false</DCC_Optimize>
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
<Defines>_DEBUG;$(Defines)</Defines>
<ILINK_FullDebugInfo>true</ILINK_FullDebugInfo>
<BCC_InlineFunctionExpansion>false</BCC_InlineFunctionExpansion>
<ILINK_DisableIncrementalLinking>true</ILINK_DisableIncrementalLinking>
<BCC_UseRegisterVariables>None</BCC_UseRegisterVariables>
<DCC_Define>DEBUG</DCC_Define>
<BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>
<IntermediateOutputDir>Debug</IntermediateOutputDir>
<TASM_DisplaySourceLines>true</TASM_DisplaySourceLines>
<BCC_StackFrames>true</BCC_StackFrames>
<BCC_DisableOptimizations>true</BCC_DisableOptimizations>
<ILINK_LibraryPath>$(BDS)\lib\debug;$(ILINK_LibraryPath)</ILINK_LibraryPath>
<TASM_Debugging>Full</TASM_Debugging>
<BCC_SourceDebuggingOn>true</BCC_SourceDebuggingOn>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<Defines>NDEBUG;$(Defines)</Defines>
<IntermediateOutputDir>Release</IntermediateOutputDir>
<ILINK_LibraryPath>$(BDS)\lib\release;$(ILINK_LibraryPath)</ILINK_LibraryPath>
<TASM_Debugging>None</TASM_Debugging>
</PropertyGroup>
<ProjectExtensions>
<Borland.Personality>CPlusPlusBuilder.Personality</Borland.Personality>
<Borland.ProjectType>CppStaticLibrary</Borland.ProjectType>
<BorlandProject>
<BorlandProject><CPlusPlusBuilder.Personality><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1033</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Debugging><Debugging Name="DebugSourceDirs"></Debugging></Debugging><Parameters><Parameters Name="RunParams"></Parameters><Parameters Name="Launcher"></Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="DebugCWD"></Parameters><Parameters Name="HostApplication"></Parameters><Parameters Name="RemoteHost"></Parameters><Parameters Name="RemotePath"></Parameters><Parameters Name="RemoteParams"></Parameters><Parameters Name="RemoteLauncher"></Parameters><Parameters Name="UseRemoteLauncher">False</Parameters><Parameters Name="RemoteCWD"></Parameters><Parameters Name="RemoteDebug">False</Parameters><Parameters Name="Debug Symbols Search Path"></Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><Excluded_Packages>
<Excluded_Packages Name="$(BDS)\bin\bcboffice2k100.bpl">CodeGear C++Builder Office 2000 Servers Package</Excluded_Packages>
<Excluded_Packages Name="$(BDS)\bin\bcbofficexp100.bpl">CodeGear C++Builder Office XP Servers Package</Excluded_Packages>
</Excluded_Packages><Linker><Linker Name="LibPrefix"></Linker><Linker Name="LibSuffix"></Linker><Linker Name="LibVersion"></Linker></Linker><ProjectProperties><ProjectProperties Name="AutoShowDeps">False</ProjectProperties><ProjectProperties Name="ManagePaths">True</ProjectProperties><ProjectProperties Name="VerifyPackages">True</ProjectProperties></ProjectProperties><HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Count">3</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item0">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item1">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\include;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item2">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\src;..\src;..\include</HistoryLists_hlIncludePath></HistoryLists_hlIncludePath><HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Count">1</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item0">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk</HistoryLists_hlILINK_LibraryPath></HistoryLists_hlILINK_LibraryPath><HistoryLists_hlDefines><HistoryLists_hlDefines Name="Count">1</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item0">NO_STRICT</HistoryLists_hlDefines></HistoryLists_hlDefines><HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Count">1</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item0">32</HistoryLists_hlTLIB_PageSize><HistoryLists_hlTLIB_PageSize Name="Item1">16</HistoryLists_hlTLIB_PageSize></HistoryLists_hlTLIB_PageSize></CPlusPlusBuilder.Personality></BorlandProject></BorlandProject>
</ProjectExtensions>
<Import Project="$(MSBuildBinPath)\Borland.Cpp.Targets" />
<ItemGroup>
<CppCompile Include="..\src\gtest_main.cc">
<BuildOrder>0</BuildOrder>
</CppCompile>
<BuildConfiguration Include="Debug">
<Key>Cfg_1</Key>
</BuildConfiguration>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
</BuildConfiguration>
</ItemGroup>
</Project>

View file

@ -1,88 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{eea63393-5ac5-4b9c-8909-d75fef2daa41}</ProjectGuid>
<Config Condition="'$(Config)'==''">Release</Config>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
<Base>true</Base>
<Cfg_1>true</Cfg_1>
<CfgParent>Base</CfgParent>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
<Base>true</Base>
<Cfg_2>true</Cfg_2>
<CfgParent>Base</CfgParent>
</PropertyGroup>
<PropertyGroup Condition="'$(Base)'!=''">
<OutputExt>exe</OutputExt>
<BCC_OptimizeForSpeed>true</BCC_OptimizeForSpeed>
<Defines>NO_STRICT</Defines>
<DCC_CBuilderOutput>JPHNE</DCC_CBuilderOutput>
<DynamicRTL>true</DynamicRTL>
<ILINK_ObjectSearchPath>..\test</ILINK_ObjectSearchPath>
<UsePackages>true</UsePackages>
<ProjectType>CppConsoleApplication</ProjectType>
<NoVCL>true</NoVCL>
<BCC_CPPCompileAlways>true</BCC_CPPCompileAlways>
<PackageImports>rtl.bpi;vcl.bpi;bcbie.bpi;vclx.bpi;vclactnband.bpi;xmlrtl.bpi;bcbsmp.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;dsnap.bpi;dsnapcon.bpi;vclib.bpi;ibxpress.bpi;adortl.bpi;dbxcds.bpi;dbexpress.bpi;DbxCommonDriver.bpi;websnap.bpi;vclie.bpi;webdsnap.bpi;inet.bpi;inetdbbde.bpi;inetdbxpress.bpi;soaprtl.bpi;Rave75VCL.bpi;teeUI.bpi;tee.bpi;teedb.bpi;IndyCore.bpi;IndySystem.bpi;IndyProtocols.bpi;IntrawebDB_90_100.bpi;Intraweb_90_100.bpi;Jcl.bpi;JclVcl.bpi;JvCoreD11R.bpi;JvSystemD11R.bpi;JvStdCtrlsD11R.bpi;JvAppFrmD11R.bpi;JvBandsD11R.bpi;JvDBD11R.bpi;JvDlgsD11R.bpi;JvBDED11R.bpi;JvCmpD11R.bpi;JvCryptD11R.bpi;JvCtrlsD11R.bpi;JvCustomD11R.bpi;JvDockingD11R.bpi;JvDotNetCtrlsD11R.bpi;JvEDID11R.bpi;JvGlobusD11R.bpi;JvHMID11R.bpi;JvInterpreterD11R.bpi;JvJansD11R.bpi;JvManagedThreadsD11R.bpi;JvMMD11R.bpi;JvNetD11R.bpi;JvPageCompsD11R.bpi;JvPluginD11R.bpi;JvPrintPreviewD11R.bpi;JvRuntimeDesignD11R.bpi;JvTimeFrameworkD11R.bpi;JvValidatorsD11R.bpi;JvWizardD11R.bpi;JvXPCtrlsD11R.bpi;VclSmp.bpi</PackageImports>
<BCC_wpar>false</BCC_wpar>
<IncludePath>$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include;..\test;..</IncludePath>
<ILINK_LibraryPath>$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;..\test</ILINK_LibraryPath>
<Multithreaded>true</Multithreaded>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1)'!=''">
<BCC_OptimizeForSpeed>false</BCC_OptimizeForSpeed>
<DCC_Optimize>false</DCC_Optimize>
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
<Defines>_DEBUG;$(Defines)</Defines>
<ILINK_FullDebugInfo>true</ILINK_FullDebugInfo>
<BCC_InlineFunctionExpansion>false</BCC_InlineFunctionExpansion>
<ILINK_DisableIncrementalLinking>true</ILINK_DisableIncrementalLinking>
<BCC_UseRegisterVariables>None</BCC_UseRegisterVariables>
<DCC_Define>DEBUG</DCC_Define>
<BCC_DebugLineNumbers>true</BCC_DebugLineNumbers>
<IntermediateOutputDir>Debug</IntermediateOutputDir>
<TASM_DisplaySourceLines>true</TASM_DisplaySourceLines>
<BCC_StackFrames>true</BCC_StackFrames>
<BCC_DisableOptimizations>true</BCC_DisableOptimizations>
<ILINK_LibraryPath>$(BDS)\lib\debug;$(ILINK_LibraryPath)</ILINK_LibraryPath>
<TASM_Debugging>Full</TASM_Debugging>
<BCC_SourceDebuggingOn>true</BCC_SourceDebuggingOn>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<Defines>NDEBUG;$(Defines)</Defines>
<IntermediateOutputDir>Release</IntermediateOutputDir>
<ILINK_LibraryPath>$(BDS)\lib\release;$(ILINK_LibraryPath)</ILINK_LibraryPath>
<TASM_Debugging>None</TASM_Debugging>
</PropertyGroup>
<ProjectExtensions>
<Borland.Personality>CPlusPlusBuilder.Personality</Borland.Personality>
<Borland.ProjectType>CppConsoleApplication</Borland.ProjectType>
<BorlandProject>
<BorlandProject><CPlusPlusBuilder.Personality><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1033</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Debugging><Debugging Name="DebugSourceDirs"></Debugging></Debugging><Parameters><Parameters Name="RunParams"></Parameters><Parameters Name="Launcher"></Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="DebugCWD"></Parameters><Parameters Name="HostApplication"></Parameters><Parameters Name="RemoteHost"></Parameters><Parameters Name="RemotePath"></Parameters><Parameters Name="RemoteParams"></Parameters><Parameters Name="RemoteLauncher"></Parameters><Parameters Name="UseRemoteLauncher">False</Parameters><Parameters Name="RemoteCWD"></Parameters><Parameters Name="RemoteDebug">False</Parameters><Parameters Name="Debug Symbols Search Path"></Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><Excluded_Packages>
<Excluded_Packages Name="$(BDS)\bin\bcboffice2k100.bpl">CodeGear C++Builder Office 2000 Servers Package</Excluded_Packages>
<Excluded_Packages Name="$(BDS)\bin\bcbofficexp100.bpl">CodeGear C++Builder Office XP Servers Package</Excluded_Packages>
</Excluded_Packages><Linker><Linker Name="LibPrefix"></Linker><Linker Name="LibSuffix"></Linker><Linker Name="LibVersion"></Linker></Linker><ProjectProperties><ProjectProperties Name="AutoShowDeps">False</ProjectProperties><ProjectProperties Name="ManagePaths">True</ProjectProperties><ProjectProperties Name="VerifyPackages">True</ProjectProperties></ProjectProperties><HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Count">3</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item0">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include;..\test;..</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item1">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include;..\test</HistoryLists_hlIncludePath><HistoryLists_hlIncludePath Name="Item2">$(BDS)\include;$(BDS)\include\dinkumware;$(BDS)\include\vcl;..\include</HistoryLists_hlIncludePath></HistoryLists_hlIncludePath><HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Count">1</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item0">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;..\test</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item1">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;..\test</HistoryLists_hlILINK_LibraryPath><HistoryLists_hlILINK_LibraryPath Name="Item2">$(BDS)\lib;$(BDS)\lib\obj;$(BDS)\lib\psdk;$(OUTPUTDIR);..\test</HistoryLists_hlILINK_LibraryPath></HistoryLists_hlILINK_LibraryPath><HistoryLists_hlDefines><HistoryLists_hlDefines Name="Count">2</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item0">NO_STRICT</HistoryLists_hlDefines><HistoryLists_hlDefines Name="Item1">STRICT</HistoryLists_hlDefines></HistoryLists_hlDefines></CPlusPlusBuilder.Personality></BorlandProject></BorlandProject>
</ProjectExtensions>
<Import Project="$(MSBuildBinPath)\Borland.Cpp.Targets" />
<ItemGroup>
<CppCompile Include="..\test\gtest_unittest.cc">
<BuildOrder>0</BuildOrder>
</CppCompile>
<CppCompile Include="gtest_link.cc">
<BuildOrder>1</BuildOrder>
</CppCompile>
<BuildConfiguration Include="Debug">
<Key>Cfg_1</Key>
</BuildConfiguration>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
</BuildConfiguration>
</ItemGroup>
</Project>

View file

@ -1,68 +0,0 @@
m4_include(m4/acx_pthread.m4)
# At this point, the Xcode project assumes the version string will be three
# integers separated by periods and surrounded by square brackets (e.g.
# "[1.0.1]"). It also asumes that there won't be any closing parenthesis
# between "AC_INIT(" and the closing ")" including comments and strings.
AC_INIT([Google C++ Testing Framework],
[1.7.0],
[googletestframework@googlegroups.com],
[gtest])
# Provide various options to initialize the Autoconf and configure processes.
AC_PREREQ([2.59])
AC_CONFIG_SRCDIR([./LICENSE])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([build-aux/config.h])
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([scripts/gtest-config], [chmod +x scripts/gtest-config])
# Initialize Automake with various options. We require at least v1.9, prevent
# pedantic complaints about package files, and enable various distribution
# targets.
AM_INIT_AUTOMAKE([1.9 dist-bzip2 dist-zip foreign subdir-objects])
# Check for programs used in building Google Test.
AC_PROG_CC
AC_PROG_CXX
AC_LANG([C++])
AC_PROG_LIBTOOL
# TODO(chandlerc@google.com): Currently we aren't running the Python tests
# against the interpreter detected by AM_PATH_PYTHON, and so we condition
# HAVE_PYTHON by requiring "python" to be in the PATH, and that interpreter's
# version to be >= 2.3. This will allow the scripts to use a "/usr/bin/env"
# hashbang.
PYTHON= # We *do not* allow the user to specify a python interpreter
AC_PATH_PROG([PYTHON],[python],[:])
AS_IF([test "$PYTHON" != ":"],
[AM_PYTHON_CHECK_VERSION([$PYTHON],[2.3],[:],[PYTHON=":"])])
AM_CONDITIONAL([HAVE_PYTHON],[test "$PYTHON" != ":"])
# Configure pthreads.
AC_ARG_WITH([pthreads],
[AS_HELP_STRING([--with-pthreads],
[use pthreads (default is yes)])],
[with_pthreads=$withval],
[with_pthreads=check])
have_pthreads=no
AS_IF([test "x$with_pthreads" != "xno"],
[ACX_PTHREAD(
[],
[AS_IF([test "x$with_pthreads" != "xcheck"],
[AC_MSG_FAILURE(
[--with-pthreads was specified, but unable to be used])])])
have_pthreads="$acx_pthread_ok"])
AM_CONDITIONAL([HAVE_PTHREADS],[test "x$have_pthreads" = "xyes"])
AC_SUBST(PTHREAD_CFLAGS)
AC_SUBST(PTHREAD_LIBS)
# TODO(chandlerc@google.com) Check for the necessary system headers.
# TODO(chandlerc@google.com) Check the types, structures, and other compiler
# and architecture characteristics.
# Output the generated files. No further autoconf macros may be used.
AC_OUTPUT

View file

@ -1,294 +0,0 @@
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
//
// The Google C++ Testing Framework (Google Test)
//
// This header file defines the public API for death tests. It is
// #included by gtest.h so a user doesn't need to include this
// directly.
#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
#include "gtest/internal/gtest-death-test-internal.h"
namespace testing {
// This flag controls the style of death tests. Valid values are "threadsafe",
// meaning that the death test child process will re-execute the test binary
// from the start, running only a single death test, or "fast",
// meaning that the child process will execute the test logic immediately
// after forking.
GTEST_DECLARE_string_(death_test_style);
#if GTEST_HAS_DEATH_TEST
namespace internal {
// Returns a Boolean value indicating whether the caller is currently
// executing in the context of the death test child process. Tools such as
// Valgrind heap checkers may need this to modify their behavior in death
// tests. IMPORTANT: This is an internal utility. Using it may break the
// implementation of death tests. User code MUST NOT use it.
GTEST_API_ bool InDeathTestChild();
} // namespace internal
// The following macros are useful for writing death tests.
// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
// executed:
//
// 1. It generates a warning if there is more than one active
// thread. This is because it's safe to fork() or clone() only
// when there is a single thread.
//
// 2. The parent process clone()s a sub-process and runs the death
// test in it; the sub-process exits with code 0 at the end of the
// death test, if it hasn't exited already.
//
// 3. The parent process waits for the sub-process to terminate.
//
// 4. The parent process checks the exit code and error message of
// the sub-process.
//
// Examples:
//
// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
// for (int i = 0; i < 5; i++) {
// EXPECT_DEATH(server.ProcessRequest(i),
// "Invalid request .* in ProcessRequest()")
// << "Failed to die on request " << i;
// }
//
// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
//
// bool KilledBySIGHUP(int exit_code) {
// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
// }
//
// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
//
// On the regular expressions used in death tests:
//
// On POSIX-compliant systems (*nix), we use the <regex.h> library,
// which uses the POSIX extended regex syntax.
//
// On other platforms (e.g. Windows), we only support a simple regex
// syntax implemented as part of Google Test. This limited
// implementation should be enough most of the time when writing
// death tests; though it lacks many features you can find in PCRE
// or POSIX extended regex syntax. For example, we don't support
// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
// repetition count ("x{5,7}"), among others.
//
// Below is the syntax that we do support. We chose it to be a
// subset of both PCRE and POSIX extended regex, so it's easy to
// learn wherever you come from. In the following: 'A' denotes a
// literal character, period (.), or a single \\ escape sequence;
// 'x' and 'y' denote regular expressions; 'm' and 'n' are for
// natural numbers.
//
// c matches any literal character c
// \\d matches any decimal digit
// \\D matches any character that's not a decimal digit
// \\f matches \f
// \\n matches \n
// \\r matches \r
// \\s matches any ASCII whitespace, including \n
// \\S matches any character that's not a whitespace
// \\t matches \t
// \\v matches \v
// \\w matches any letter, _, or decimal digit
// \\W matches any character that \\w doesn't match
// \\c matches any literal character c, which must be a punctuation
// . matches any single character except \n
// A? matches 0 or 1 occurrences of A
// A* matches 0 or many occurrences of A
// A+ matches 1 or many occurrences of A
// ^ matches the beginning of a string (not that of each line)
// $ matches the end of a string (not that of each line)
// xy matches x followed by y
//
// If you accidentally use PCRE or POSIX extended regex features
// not implemented by us, you will get a run-time failure. In that
// case, please try to rewrite your regular expression within the
// above syntax.
//
// This implementation is *not* meant to be as highly tuned or robust
// as a compiled regex library, but should perform well enough for a
// death test, which already incurs significant overhead by launching
// a child process.
//
// Known caveats:
//
// A "threadsafe" style death test obtains the path to the test
// program from argv[0] and re-executes it in the sub-process. For
// simplicity, the current implementation doesn't search the PATH
// when launching the sub-process. This means that the user must
// invoke the test program via a path that contains at least one
// path separator (e.g. path/to/foo_test and
// /absolute/path/to/bar_test are fine, but foo_test is not). This
// is rarely a problem as people usually don't put the test binary
// directory in PATH.
//
// TODO(wan@google.com): make thread-safe death tests search the PATH.
// Asserts that a given statement causes the program to exit, with an
// integer exit status that satisfies predicate, and emitting error output
// that matches regex.
# define ASSERT_EXIT(statement, predicate, regex) \
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
// Like ASSERT_EXIT, but continues on to successive tests in the
// test case, if any:
# define EXPECT_EXIT(statement, predicate, regex) \
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
// Asserts that a given statement causes the program to exit, either by
// explicitly exiting with a nonzero exit code or being killed by a
// signal, and emitting error output that matches regex.
# define ASSERT_DEATH(statement, regex) \
ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
// Like ASSERT_DEATH, but continues on to successive tests in the
// test case, if any:
# define EXPECT_DEATH(statement, regex) \
EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
// Tests that an exit code describes a normal exit with a given exit code.
class GTEST_API_ ExitedWithCode {
public:
explicit ExitedWithCode(int exit_code);
bool operator()(int exit_status) const;
private:
// No implementation - assignment is unsupported.
void operator=(const ExitedWithCode& other);
const int exit_code_;
};
# if !GTEST_OS_WINDOWS
// Tests that an exit code describes an exit due to termination by a
// given signal.
class GTEST_API_ KilledBySignal {
public:
explicit KilledBySignal(int signum);
bool operator()(int exit_status) const;
private:
const int signum_;
};
# endif // !GTEST_OS_WINDOWS
// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
// The death testing framework causes this to have interesting semantics,
// since the sideeffects of the call are only visible in opt mode, and not
// in debug mode.
//
// In practice, this can be used to test functions that utilize the
// LOG(DFATAL) macro using the following style:
//
// int DieInDebugOr12(int* sideeffect) {
// if (sideeffect) {
// *sideeffect = 12;
// }
// LOG(DFATAL) << "death";
// return 12;
// }
//
// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) {
// int sideeffect = 0;
// // Only asserts in dbg.
// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
//
// #ifdef NDEBUG
// // opt-mode has sideeffect visible.
// EXPECT_EQ(12, sideeffect);
// #else
// // dbg-mode no visible sideeffect.
// EXPECT_EQ(0, sideeffect);
// #endif
// }
//
// This will assert that DieInDebugReturn12InOpt() crashes in debug
// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
// appropriate fallback value (12 in this case) in opt mode. If you
// need to test that a function has appropriate side-effects in opt
// mode, include assertions against the side-effects. A general
// pattern for this is:
//
// EXPECT_DEBUG_DEATH({
// // Side-effects here will have an effect after this statement in
// // opt mode, but none in debug mode.
// EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
// }, "death");
//
# ifdef NDEBUG
# define EXPECT_DEBUG_DEATH(statement, regex) \
GTEST_EXECUTE_STATEMENT_(statement, regex)
# define ASSERT_DEBUG_DEATH(statement, regex) \
GTEST_EXECUTE_STATEMENT_(statement, regex)
# else
# define EXPECT_DEBUG_DEATH(statement, regex) \
EXPECT_DEATH(statement, regex)
# define ASSERT_DEBUG_DEATH(statement, regex) \
ASSERT_DEATH(statement, regex)
# endif // NDEBUG for EXPECT_DEBUG_DEATH
#endif // GTEST_HAS_DEATH_TEST
// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
// death tests are supported; otherwise they just issue a warning. This is
// useful when you are combining death test assertions with normal test
// assertions in one test.
#if GTEST_HAS_DEATH_TEST
# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
EXPECT_DEATH(statement, regex)
# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
ASSERT_DEATH(statement, regex)
#else
# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
#endif
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_

View file

@ -1,250 +0,0 @@
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
//
// The Google C++ Testing Framework (Google Test)
//
// This header file defines the Message class.
//
// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
// leave some internal implementation details in this header file.
// They are clearly marked by comments like this:
//
// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
//
// Such code is NOT meant to be used by a user directly, and is subject
// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user
// program!
#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
#include <limits>
#include "gtest/internal/gtest-port.h"
// Ensures that there is at least one operator<< in the global namespace.
// See Message& operator<<(...) below for why.
void operator<<(const testing::internal::Secret&, int);
namespace testing {
// The Message class works like an ostream repeater.
//
// Typical usage:
//
// 1. You stream a bunch of values to a Message object.
// It will remember the text in a stringstream.
// 2. Then you stream the Message object to an ostream.
// This causes the text in the Message to be streamed
// to the ostream.
//
// For example;
//
// testing::Message foo;
// foo << 1 << " != " << 2;
// std::cout << foo;
//
// will print "1 != 2".
//
// Message is not intended to be inherited from. In particular, its
// destructor is not virtual.
//
// Note that stringstream behaves differently in gcc and in MSVC. You
// can stream a NULL char pointer to it in the former, but not in the
// latter (it causes an access violation if you do). The Message
// class hides this difference by treating a NULL char pointer as
// "(null)".
class GTEST_API_ Message {
private:
// The type of basic IO manipulators (endl, ends, and flush) for
// narrow streams.
typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
public:
// Constructs an empty Message.
Message();
// Copy constructor.
Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT
*ss_ << msg.GetString();
}
// Constructs a Message from a C-string.
explicit Message(const char* str) : ss_(new ::std::stringstream) {
*ss_ << str;
}
#if GTEST_OS_SYMBIAN
// Streams a value (either a pointer or not) to this object.
template <typename T>
inline Message& operator <<(const T& value) {
StreamHelper(typename internal::is_pointer<T>::type(), value);
return *this;
}
#else
// Streams a non-pointer value to this object.
template <typename T>
inline Message& operator <<(const T& val) {
// Some libraries overload << for STL containers. These
// overloads are defined in the global namespace instead of ::std.
//
// C++'s symbol lookup rule (i.e. Koenig lookup) says that these
// overloads are visible in either the std namespace or the global
// namespace, but not other namespaces, including the testing
// namespace which Google Test's Message class is in.
//
// To allow STL containers (and other types that has a << operator
// defined in the global namespace) to be used in Google Test
// assertions, testing::Message must access the custom << operator
// from the global namespace. With this using declaration,
// overloads of << defined in the global namespace and those
// visible via Koenig lookup are both exposed in this function.
using ::operator <<;
*ss_ << val;
return *this;
}
// Streams a pointer value to this object.
//
// This function is an overload of the previous one. When you
// stream a pointer to a Message, this definition will be used as it
// is more specialized. (The C++ Standard, section
// [temp.func.order].) If you stream a non-pointer, then the
// previous definition will be used.
//
// The reason for this overload is that streaming a NULL pointer to
// ostream is undefined behavior. Depending on the compiler, you
// may get "0", "(nil)", "(null)", or an access violation. To
// ensure consistent result across compilers, we always treat NULL
// as "(null)".
template <typename T>
inline Message& operator <<(T* const& pointer) { // NOLINT
if (pointer == NULL) {
*ss_ << "(null)";
} else {
*ss_ << pointer;
}
return *this;
}
#endif // GTEST_OS_SYMBIAN
// Since the basic IO manipulators are overloaded for both narrow
// and wide streams, we have to provide this specialized definition
// of operator <<, even though its body is the same as the
// templatized version above. Without this definition, streaming
// endl or other basic IO manipulators to Message will confuse the
// compiler.
Message& operator <<(BasicNarrowIoManip val) {
*ss_ << val;
return *this;
}
// Instead of 1/0, we want to see true/false for bool values.
Message& operator <<(bool b) {
return *this << (b ? "true" : "false");
}
// These two overloads allow streaming a wide C string to a Message
// using the UTF-8 encoding.
Message& operator <<(const wchar_t* wide_c_str);
Message& operator <<(wchar_t* wide_c_str);
#if GTEST_HAS_STD_WSTRING
// Converts the given wide string to a narrow string using the UTF-8
// encoding, and streams the result to this Message object.
Message& operator <<(const ::std::wstring& wstr);
#endif // GTEST_HAS_STD_WSTRING
#if GTEST_HAS_GLOBAL_WSTRING
// Converts the given wide string to a narrow string using the UTF-8
// encoding, and streams the result to this Message object.
Message& operator <<(const ::wstring& wstr);
#endif // GTEST_HAS_GLOBAL_WSTRING
// Gets the text streamed to this object so far as an std::string.
// Each '\0' character in the buffer is replaced with "\\0".
//
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
std::string GetString() const;
private:
#if GTEST_OS_SYMBIAN
// These are needed as the Nokia Symbian Compiler cannot decide between
// const T& and const T* in a function template. The Nokia compiler _can_
// decide between class template specializations for T and T*, so a
// tr1::type_traits-like is_pointer works, and we can overload on that.
template <typename T>
inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) {
if (pointer == NULL) {
*ss_ << "(null)";
} else {
*ss_ << pointer;
}
}
template <typename T>
inline void StreamHelper(internal::false_type /*is_pointer*/,
const T& value) {
// See the comments in Message& operator <<(const T&) above for why
// we need this using statement.
using ::operator <<;
*ss_ << value;
}
#endif // GTEST_OS_SYMBIAN
// We'll hold the text streamed to this object here.
const internal::scoped_ptr< ::std::stringstream> ss_;
// We declare (but don't implement) this to prevent the compiler
// from implementing the assignment operator.
void operator=(const Message&);
};
// Streams a Message to an ostream.
inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
return os << sb.GetString();
}
namespace internal {
// Converts a streamable value to an std::string. A NULL pointer is
// converted to "(null)". When the input value is a ::string,
// ::std::string, ::wstring, or ::std::wstring object, each NUL
// character in it is replaced with "\\0".
template <typename T>
std::string StreamableToString(const T& streamable) {
return (Message() << streamable).GetString();
}
} // namespace internal
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_

File diff suppressed because it is too large Load diff

View file

@ -1,487 +0,0 @@
$$ -*- mode: c++; -*-
$var n = 50 $$ Maximum length of Values arguments we want to support.
$var maxtuple = 10 $$ Maximum number of Combine arguments we want to support.
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: vladl@google.com (Vlad Losev)
//
// Macros and functions for implementing parameterized tests
// in Google C++ Testing Framework (Google Test)
//
// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
//
#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
// Value-parameterized tests allow you to test your code with different
// parameters without writing multiple copies of the same test.
//
// Here is how you use value-parameterized tests:
#if 0
// To write value-parameterized tests, first you should define a fixture
// class. It is usually derived from testing::TestWithParam<T> (see below for
// another inheritance scheme that's sometimes useful in more complicated
// class hierarchies), where the type of your parameter values.
// TestWithParam<T> is itself derived from testing::Test. T can be any
// copyable type. If it's a raw pointer, you are responsible for managing the
// lifespan of the pointed values.
class FooTest : public ::testing::TestWithParam<const char*> {
// You can implement all the usual class fixture members here.
};
// Then, use the TEST_P macro to define as many parameterized tests
// for this fixture as you want. The _P suffix is for "parameterized"
// or "pattern", whichever you prefer to think.
TEST_P(FooTest, DoesBlah) {
// Inside a test, access the test parameter with the GetParam() method
// of the TestWithParam<T> class:
EXPECT_TRUE(foo.Blah(GetParam()));
...
}
TEST_P(FooTest, HasBlahBlah) {
...
}
// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
// case with any set of parameters you want. Google Test defines a number
// of functions for generating test parameters. They return what we call
// (surprise!) parameter generators. Here is a summary of them, which
// are all in the testing namespace:
//
//
// Range(begin, end [, step]) - Yields values {begin, begin+step,
// begin+step+step, ...}. The values do not
// include end. step defaults to 1.
// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}.
// ValuesIn(container) - Yields values from a C-style array, an STL
// ValuesIn(begin,end) container, or an iterator range [begin, end).
// Bool() - Yields sequence {false, true}.
// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product
// for the math savvy) of the values generated
// by the N generators.
//
// For more details, see comments at the definitions of these functions below
// in this file.
//
// The following statement will instantiate tests from the FooTest test case
// each with parameter values "meeny", "miny", and "moe".
INSTANTIATE_TEST_CASE_P(InstantiationName,
FooTest,
Values("meeny", "miny", "moe"));
// To distinguish different instances of the pattern, (yes, you
// can instantiate it more then once) the first argument to the
// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
// actual test case name. Remember to pick unique prefixes for different
// instantiations. The tests from the instantiation above will have
// these names:
//
// * InstantiationName/FooTest.DoesBlah/0 for "meeny"
// * InstantiationName/FooTest.DoesBlah/1 for "miny"
// * InstantiationName/FooTest.DoesBlah/2 for "moe"
// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
// * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
// * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
//
// You can use these names in --gtest_filter.
//
// This statement will instantiate all tests from FooTest again, each
// with parameter values "cat" and "dog":
const char* pets[] = {"cat", "dog"};
INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
// The tests from the instantiation above will have these names:
//
// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
//
// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
// in the given test case, whether their definitions come before or
// AFTER the INSTANTIATE_TEST_CASE_P statement.
//
// Please also note that generator expressions (including parameters to the
// generators) are evaluated in InitGoogleTest(), after main() has started.
// This allows the user on one hand, to adjust generator parameters in order
// to dynamically determine a set of tests to run and on the other hand,
// give the user a chance to inspect the generated tests with Google Test
// reflection API before RUN_ALL_TESTS() is executed.
//
// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
// for more examples.
//
// In the future, we plan to publish the API for defining new parameter
// generators. But for now this interface remains part of the internal
// implementation and is subject to change.
//
//
// A parameterized test fixture must be derived from testing::Test and from
// testing::WithParamInterface<T>, where T is the type of the parameter
// values. Inheriting from TestWithParam<T> satisfies that requirement because
// TestWithParam<T> inherits from both Test and WithParamInterface. In more
// complicated hierarchies, however, it is occasionally useful to inherit
// separately from Test and WithParamInterface. For example:
class BaseTest : public ::testing::Test {
// You can inherit all the usual members for a non-parameterized test
// fixture here.
};
class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
// The usual test fixture members go here too.
};
TEST_F(BaseTest, HasFoo) {
// This is an ordinary non-parameterized test.
}
TEST_P(DerivedTest, DoesBlah) {
// GetParam works just the same here as if you inherit from TestWithParam.
EXPECT_TRUE(foo.Blah(GetParam()));
}
#endif // 0
#include "gtest/internal/gtest-port.h"
#if !GTEST_OS_SYMBIAN
# include <utility>
#endif
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
#include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-param-util.h"
#include "gtest/internal/gtest-param-util-generated.h"
#if GTEST_HAS_PARAM_TEST
namespace testing {
// Functions producing parameter generators.
//
// Google Test uses these generators to produce parameters for value-
// parameterized tests. When a parameterized test case is instantiated
// with a particular generator, Google Test creates and runs tests
// for each element in the sequence produced by the generator.
//
// In the following sample, tests from test case FooTest are instantiated
// each three times with parameter values 3, 5, and 8:
//
// class FooTest : public TestWithParam<int> { ... };
//
// TEST_P(FooTest, TestThis) {
// }
// TEST_P(FooTest, TestThat) {
// }
// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
//
// Range() returns generators providing sequences of values in a range.
//
// Synopsis:
// Range(start, end)
// - returns a generator producing a sequence of values {start, start+1,
// start+2, ..., }.
// Range(start, end, step)
// - returns a generator producing a sequence of values {start, start+step,
// start+step+step, ..., }.
// Notes:
// * The generated sequences never include end. For example, Range(1, 5)
// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
// returns a generator producing {1, 3, 5, 7}.
// * start and end must have the same type. That type may be any integral or
// floating-point type or a user defined type satisfying these conditions:
// * It must be assignable (have operator=() defined).
// * It must have operator+() (operator+(int-compatible type) for
// two-operand version).
// * It must have operator<() defined.
// Elements in the resulting sequences will also have that type.
// * Condition start < end must be satisfied in order for resulting sequences
// to contain any elements.
//
template <typename T, typename IncrementT>
internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
return internal::ParamGenerator<T>(
new internal::RangeGenerator<T, IncrementT>(start, end, step));
}
template <typename T>
internal::ParamGenerator<T> Range(T start, T end) {
return Range(start, end, 1);
}
// ValuesIn() function allows generation of tests with parameters coming from
// a container.
//
// Synopsis:
// ValuesIn(const T (&array)[N])
// - returns a generator producing sequences with elements from
// a C-style array.
// ValuesIn(const Container& container)
// - returns a generator producing sequences with elements from
// an STL-style container.
// ValuesIn(Iterator begin, Iterator end)
// - returns a generator producing sequences with elements from
// a range [begin, end) defined by a pair of STL-style iterators. These
// iterators can also be plain C pointers.
//
// Please note that ValuesIn copies the values from the containers
// passed in and keeps them to generate tests in RUN_ALL_TESTS().
//
// Examples:
//
// This instantiates tests from test case StringTest
// each with C-string values of "foo", "bar", and "baz":
//
// const char* strings[] = {"foo", "bar", "baz"};
// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
//
// This instantiates tests from test case StlStringTest
// each with STL strings with values "a" and "b":
//
// ::std::vector< ::std::string> GetParameterStrings() {
// ::std::vector< ::std::string> v;
// v.push_back("a");
// v.push_back("b");
// return v;
// }
//
// INSTANTIATE_TEST_CASE_P(CharSequence,
// StlStringTest,
// ValuesIn(GetParameterStrings()));
//
//
// This will also instantiate tests from CharTest
// each with parameter values 'a' and 'b':
//
// ::std::list<char> GetParameterChars() {
// ::std::list<char> list;
// list.push_back('a');
// list.push_back('b');
// return list;
// }
// ::std::list<char> l = GetParameterChars();
// INSTANTIATE_TEST_CASE_P(CharSequence2,
// CharTest,
// ValuesIn(l.begin(), l.end()));
//
template <typename ForwardIterator>
internal::ParamGenerator<
typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
ValuesIn(ForwardIterator begin, ForwardIterator end) {
typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
::value_type ParamType;
return internal::ParamGenerator<ParamType>(
new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
}
template <typename T, size_t N>
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
return ValuesIn(array, array + N);
}
template <class Container>
internal::ParamGenerator<typename Container::value_type> ValuesIn(
const Container& container) {
return ValuesIn(container.begin(), container.end());
}
// Values() allows generating tests from explicitly specified list of
// parameters.
//
// Synopsis:
// Values(T v1, T v2, ..., T vN)
// - returns a generator producing sequences with elements v1, v2, ..., vN.
//
// For example, this instantiates tests from test case BarTest each
// with values "one", "two", and "three":
//
// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
//
// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
// The exact type of values will depend on the type of parameter in BazTest.
//
// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
//
// Currently, Values() supports from 1 to $n parameters.
//
$range i 1..n
$for i [[
$range j 1..i
template <$for j, [[typename T$j]]>
internal::ValueArray$i<$for j, [[T$j]]> Values($for j, [[T$j v$j]]) {
return internal::ValueArray$i<$for j, [[T$j]]>($for j, [[v$j]]);
}
]]
// Bool() allows generating tests with parameters in a set of (false, true).
//
// Synopsis:
// Bool()
// - returns a generator producing sequences with elements {false, true}.
//
// It is useful when testing code that depends on Boolean flags. Combinations
// of multiple flags can be tested when several Bool()'s are combined using
// Combine() function.
//
// In the following example all tests in the test case FlagDependentTest
// will be instantiated twice with parameters false and true.
//
// class FlagDependentTest : public testing::TestWithParam<bool> {
// virtual void SetUp() {
// external_flag = GetParam();
// }
// }
// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
//
inline internal::ParamGenerator<bool> Bool() {
return Values(false, true);
}
# if GTEST_HAS_COMBINE
// Combine() allows the user to combine two or more sequences to produce
// values of a Cartesian product of those sequences' elements.
//
// Synopsis:
// Combine(gen1, gen2, ..., genN)
// - returns a generator producing sequences with elements coming from
// the Cartesian product of elements from the sequences generated by
// gen1, gen2, ..., genN. The sequence elements will have a type of
// tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
// of elements from sequences produces by gen1, gen2, ..., genN.
//
// Combine can have up to $maxtuple arguments. This number is currently limited
// by the maximum number of elements in the tuple implementation used by Google
// Test.
//
// Example:
//
// This will instantiate tests in test case AnimalTest each one with
// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
// tuple("dog", BLACK), and tuple("dog", WHITE):
//
// enum Color { BLACK, GRAY, WHITE };
// class AnimalTest
// : public testing::TestWithParam<tuple<const char*, Color> > {...};
//
// TEST_P(AnimalTest, AnimalLooksNice) {...}
//
// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
// Combine(Values("cat", "dog"),
// Values(BLACK, WHITE)));
//
// This will instantiate tests in FlagDependentTest with all variations of two
// Boolean flags:
//
// class FlagDependentTest
// : public testing::TestWithParam<tuple<bool, bool> > {
// virtual void SetUp() {
// // Assigns external_flag_1 and external_flag_2 values from the tuple.
// tie(external_flag_1, external_flag_2) = GetParam();
// }
// };
//
// TEST_P(FlagDependentTest, TestFeature1) {
// // Test your code using external_flag_1 and external_flag_2 here.
// }
// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
// Combine(Bool(), Bool()));
//
$range i 2..maxtuple
$for i [[
$range j 1..i
template <$for j, [[typename Generator$j]]>
internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine(
$for j, [[const Generator$j& g$j]]) {
return internal::CartesianProductHolder$i<$for j, [[Generator$j]]>(
$for j, [[g$j]]);
}
]]
# endif // GTEST_HAS_COMBINE
# define TEST_P(test_case_name, test_name) \
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
: public test_case_name { \
public: \
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
virtual void TestBody(); \
private: \
static int AddToRegistry() { \
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
GetTestCasePatternHolder<test_case_name>(\
#test_case_name, __FILE__, __LINE__)->AddTestPattern(\
#test_case_name, \
#test_name, \
new ::testing::internal::TestMetaFactory< \
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \
return 0; \
} \
static int gtest_registering_dummy_; \
GTEST_DISALLOW_COPY_AND_ASSIGN_(\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
}; \
int GTEST_TEST_CLASS_NAME_(test_case_name, \
test_name)::gtest_registering_dummy_ = \
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
::testing::internal::ParamGenerator<test_case_name::ParamType> \
gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
int gtest_##prefix##test_case_name##_dummy_ = \
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
GetTestCasePatternHolder<test_case_name>(\
#test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\
#prefix, \
&gtest_##prefix##test_case_name##_EvalGenerator_, \
__FILE__, __LINE__)
} // namespace testing
#endif // GTEST_HAS_PARAM_TEST
#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_

View file

@ -1,855 +0,0 @@
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Test - The Google C++ Testing Framework
//
// This file implements a universal value printer that can print a
// value of any type T:
//
// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
//
// A user can teach this function how to print a class type T by
// defining either operator<<() or PrintTo() in the namespace that
// defines T. More specifically, the FIRST defined function in the
// following list will be used (assuming T is defined in namespace
// foo):
//
// 1. foo::PrintTo(const T&, ostream*)
// 2. operator<<(ostream&, const T&) defined in either foo or the
// global namespace.
//
// If none of the above is defined, it will print the debug string of
// the value if it is a protocol buffer, or print the raw bytes in the
// value otherwise.
//
// To aid debugging: when T is a reference type, the address of the
// value is also printed; when T is a (const) char pointer, both the
// pointer value and the NUL-terminated string it points to are
// printed.
//
// We also provide some convenient wrappers:
//
// // Prints a value to a string. For a (const or not) char
// // pointer, the NUL-terminated string (but not the pointer) is
// // printed.
// std::string ::testing::PrintToString(const T& value);
//
// // Prints a value tersely: for a reference type, the referenced
// // value (but not the address) is printed; for a (const or not) char
// // pointer, the NUL-terminated string (but not the pointer) is
// // printed.
// void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
//
// // Prints value using the type inferred by the compiler. The difference
// // from UniversalTersePrint() is that this function prints both the
// // pointer and the NUL-terminated string for a (const or not) char pointer.
// void ::testing::internal::UniversalPrint(const T& value, ostream*);
//
// // Prints the fields of a tuple tersely to a string vector, one
// // element for each field. Tuple support must be enabled in
// // gtest-port.h.
// std::vector<string> UniversalTersePrintTupleFieldsToStrings(
// const Tuple& value);
//
// Known limitation:
//
// The print primitives print the elements of an STL-style container
// using the compiler-inferred type of *iter where iter is a
// const_iterator of the container. When const_iterator is an input
// iterator but not a forward iterator, this inferred type may not
// match value_type, and the print output may be incorrect. In
// practice, this is rarely a problem as for most containers
// const_iterator is a forward iterator. We'll fix this if there's an
// actual need for it. Note that this fix cannot rely on value_type
// being defined as many user-defined container types don't have
// value_type.
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
#include <ostream> // NOLINT
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "gtest/internal/gtest-port.h"
#include "gtest/internal/gtest-internal.h"
namespace testing {
// Definitions in the 'internal' and 'internal2' name spaces are
// subject to change without notice. DO NOT USE THEM IN USER CODE!
namespace internal2 {
// Prints the given number of bytes in the given object to the given
// ostream.
GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
size_t count,
::std::ostream* os);
// For selecting which printer to use when a given type has neither <<
// nor PrintTo().
enum TypeKind {
kProtobuf, // a protobuf type
kConvertibleToInteger, // a type implicitly convertible to BiggestInt
// (e.g. a named or unnamed enum type)
kOtherType // anything else
};
// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
// by the universal printer to print a value of type T when neither
// operator<< nor PrintTo() is defined for T, where kTypeKind is the
// "kind" of T as defined by enum TypeKind.
template <typename T, TypeKind kTypeKind>
class TypeWithoutFormatter {
public:
// This default version is called when kTypeKind is kOtherType.
static void PrintValue(const T& value, ::std::ostream* os) {
PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
sizeof(value), os);
}
};
// We print a protobuf using its ShortDebugString() when the string
// doesn't exceed this many characters; otherwise we print it using
// DebugString() for better readability.
const size_t kProtobufOneLinerMaxLength = 50;
template <typename T>
class TypeWithoutFormatter<T, kProtobuf> {
public:
static void PrintValue(const T& value, ::std::ostream* os) {
const ::testing::internal::string short_str = value.ShortDebugString();
const ::testing::internal::string pretty_str =
short_str.length() <= kProtobufOneLinerMaxLength ?
short_str : ("\n" + value.DebugString());
*os << ("<" + pretty_str + ">");
}
};
template <typename T>
class TypeWithoutFormatter<T, kConvertibleToInteger> {
public:
// Since T has no << operator or PrintTo() but can be implicitly
// converted to BiggestInt, we print it as a BiggestInt.
//
// Most likely T is an enum type (either named or unnamed), in which
// case printing it as an integer is the desired behavior. In case
// T is not an enum, printing it as an integer is the best we can do
// given that it has no user-defined printer.
static void PrintValue(const T& value, ::std::ostream* os) {
const internal::BiggestInt kBigInt = value;
*os << kBigInt;
}
};
// Prints the given value to the given ostream. If the value is a
// protocol message, its debug string is printed; if it's an enum or
// of a type implicitly convertible to BiggestInt, it's printed as an
// integer; otherwise the bytes in the value are printed. This is
// what UniversalPrinter<T>::Print() does when it knows nothing about
// type T and T has neither << operator nor PrintTo().
//
// A user can override this behavior for a class type Foo by defining
// a << operator in the namespace where Foo is defined.
//
// We put this operator in namespace 'internal2' instead of 'internal'
// to simplify the implementation, as much code in 'internal' needs to
// use << in STL, which would conflict with our own << were it defined
// in 'internal'.
//
// Note that this operator<< takes a generic std::basic_ostream<Char,
// CharTraits> type instead of the more restricted std::ostream. If
// we define it to take an std::ostream instead, we'll get an
// "ambiguous overloads" compiler error when trying to print a type
// Foo that supports streaming to std::basic_ostream<Char,
// CharTraits>, as the compiler cannot tell whether
// operator<<(std::ostream&, const T&) or
// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
// specific.
template <typename Char, typename CharTraits, typename T>
::std::basic_ostream<Char, CharTraits>& operator<<(
::std::basic_ostream<Char, CharTraits>& os, const T& x) {
TypeWithoutFormatter<T,
(internal::IsAProtocolMessage<T>::value ? kProtobuf :
internal::ImplicitlyConvertible<const T&, internal::BiggestInt>::value ?
kConvertibleToInteger : kOtherType)>::PrintValue(x, &os);
return os;
}
} // namespace internal2
} // namespace testing
// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
// magic needed for implementing UniversalPrinter won't work.
namespace testing_internal {
// Used to print a value that is not an STL-style container when the
// user doesn't define PrintTo() for it.
template <typename T>
void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
// With the following statement, during unqualified name lookup,
// testing::internal2::operator<< appears as if it was declared in
// the nearest enclosing namespace that contains both
// ::testing_internal and ::testing::internal2, i.e. the global
// namespace. For more details, refer to the C++ Standard section
// 7.3.4-1 [namespace.udir]. This allows us to fall back onto
// testing::internal2::operator<< in case T doesn't come with a <<
// operator.
//
// We cannot write 'using ::testing::internal2::operator<<;', which
// gcc 3.3 fails to compile due to a compiler bug.
using namespace ::testing::internal2; // NOLINT
// Assuming T is defined in namespace foo, in the next statement,
// the compiler will consider all of:
//
// 1. foo::operator<< (thanks to Koenig look-up),
// 2. ::operator<< (as the current namespace is enclosed in ::),
// 3. testing::internal2::operator<< (thanks to the using statement above).
//
// The operator<< whose type matches T best will be picked.
//
// We deliberately allow #2 to be a candidate, as sometimes it's
// impossible to define #1 (e.g. when foo is ::std, defining
// anything in it is undefined behavior unless you are a compiler
// vendor.).
*os << value;
}
} // namespace testing_internal
namespace testing {
namespace internal {
// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
// value to the given ostream. The caller must ensure that
// 'ostream_ptr' is not NULL, or the behavior is undefined.
//
// We define UniversalPrinter as a class template (as opposed to a
// function template), as we need to partially specialize it for
// reference types, which cannot be done with function templates.
template <typename T>
class UniversalPrinter;
template <typename T>
void UniversalPrint(const T& value, ::std::ostream* os);
// Used to print an STL-style container when the user doesn't define
// a PrintTo() for it.
template <typename C>
void DefaultPrintTo(IsContainer /* dummy */,
false_type /* is not a pointer */,
const C& container, ::std::ostream* os) {
const size_t kMaxCount = 32; // The maximum number of elements to print.
*os << '{';
size_t count = 0;
for (typename C::const_iterator it = container.begin();
it != container.end(); ++it, ++count) {
if (count > 0) {
*os << ',';
if (count == kMaxCount) { // Enough has been printed.
*os << " ...";
break;
}
}
*os << ' ';
// We cannot call PrintTo(*it, os) here as PrintTo() doesn't
// handle *it being a native array.
internal::UniversalPrint(*it, os);
}
if (count > 0) {
*os << ' ';
}
*os << '}';
}
// Used to print a pointer that is neither a char pointer nor a member
// pointer, when the user doesn't define PrintTo() for it. (A member
// variable pointer or member function pointer doesn't really point to
// a location in the address space. Their representation is
// implementation-defined. Therefore they will be printed as raw
// bytes.)
template <typename T>
void DefaultPrintTo(IsNotContainer /* dummy */,
true_type /* is a pointer */,
T* p, ::std::ostream* os) {
if (p == NULL) {
*os << "NULL";
} else {
// C++ doesn't allow casting from a function pointer to any object
// pointer.
//
// IsTrue() silences warnings: "Condition is always true",
// "unreachable code".
if (IsTrue(ImplicitlyConvertible<T*, const void*>::value)) {
// T is not a function type. We just call << to print p,
// relying on ADL to pick up user-defined << for their pointer
// types, if any.
*os << p;
} else {
// T is a function type, so '*os << p' doesn't do what we want
// (it just prints p as bool). We want to print p as a const
// void*. However, we cannot cast it to const void* directly,
// even using reinterpret_cast, as earlier versions of gcc
// (e.g. 3.4.5) cannot compile the cast when p is a function
// pointer. Casting to UInt64 first solves the problem.
*os << reinterpret_cast<const void*>(
reinterpret_cast<internal::UInt64>(p));
}
}
}
// Used to print a non-container, non-pointer value when the user
// doesn't define PrintTo() for it.
template <typename T>
void DefaultPrintTo(IsNotContainer /* dummy */,
false_type /* is not a pointer */,
const T& value, ::std::ostream* os) {
::testing_internal::DefaultPrintNonContainerTo(value, os);
}
// Prints the given value using the << operator if it has one;
// otherwise prints the bytes in it. This is what
// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
// or overloaded for type T.
//
// A user can override this behavior for a class type Foo by defining
// an overload of PrintTo() in the namespace where Foo is defined. We
// give the user this option as sometimes defining a << operator for
// Foo is not desirable (e.g. the coding style may prevent doing it,
// or there is already a << operator but it doesn't do what the user
// wants).
template <typename T>
void PrintTo(const T& value, ::std::ostream* os) {
// DefaultPrintTo() is overloaded. The type of its first two
// arguments determine which version will be picked. If T is an
// STL-style container, the version for container will be called; if
// T is a pointer, the pointer version will be called; otherwise the
// generic version will be called.
//
// Note that we check for container types here, prior to we check
// for protocol message types in our operator<<. The rationale is:
//
// For protocol messages, we want to give people a chance to
// override Google Mock's format by defining a PrintTo() or
// operator<<. For STL containers, other formats can be
// incompatible with Google Mock's format for the container
// elements; therefore we check for container types here to ensure
// that our format is used.
//
// The second argument of DefaultPrintTo() is needed to bypass a bug
// in Symbian's C++ compiler that prevents it from picking the right
// overload between:
//
// PrintTo(const T& x, ...);
// PrintTo(T* x, ...);
DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
}
// The following list of PrintTo() overloads tells
// UniversalPrinter<T>::Print() how to print standard types (built-in
// types, strings, plain arrays, and pointers).
// Overloads for various char types.
GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os);
GTEST_API_ void PrintTo(signed char c, ::std::ostream* os);
inline void PrintTo(char c, ::std::ostream* os) {
// When printing a plain char, we always treat it as unsigned. This
// way, the output won't be affected by whether the compiler thinks
// char is signed or not.
PrintTo(static_cast<unsigned char>(c), os);
}
// Overloads for other simple built-in types.
inline void PrintTo(bool x, ::std::ostream* os) {
*os << (x ? "true" : "false");
}
// Overload for wchar_t type.
// Prints a wchar_t as a symbol if it is printable or as its internal
// code otherwise and also as its decimal code (except for L'\0').
// The L'\0' char is printed as "L'\\0'". The decimal code is printed
// as signed integer when wchar_t is implemented by the compiler
// as a signed type and is printed as an unsigned integer when wchar_t
// is implemented as an unsigned type.
GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
// Overloads for C strings.
GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
inline void PrintTo(char* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const char*>(s), os);
}
// signed/unsigned char is often used for representing binary data, so
// we print pointers to it as void* to be safe.
inline void PrintTo(const signed char* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
}
inline void PrintTo(signed char* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
}
inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
}
inline void PrintTo(unsigned char* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
}
// MSVC can be configured to define wchar_t as a typedef of unsigned
// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
// type. When wchar_t is a typedef, defining an overload for const
// wchar_t* would cause unsigned short* be printed as a wide string,
// possibly causing invalid memory accesses.
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
// Overloads for wide C strings
GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
inline void PrintTo(wchar_t* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const wchar_t*>(s), os);
}
#endif
// Overload for C arrays. Multi-dimensional arrays are printed
// properly.
// Prints the given number of elements in an array, without printing
// the curly braces.
template <typename T>
void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
UniversalPrint(a[0], os);
for (size_t i = 1; i != count; i++) {
*os << ", ";
UniversalPrint(a[i], os);
}
}
// Overloads for ::string and ::std::string.
#if GTEST_HAS_GLOBAL_STRING
GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os);
inline void PrintTo(const ::string& s, ::std::ostream* os) {
PrintStringTo(s, os);
}
#endif // GTEST_HAS_GLOBAL_STRING
GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
PrintStringTo(s, os);
}
// Overloads for ::wstring and ::std::wstring.
#if GTEST_HAS_GLOBAL_WSTRING
GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os);
inline void PrintTo(const ::wstring& s, ::std::ostream* os) {
PrintWideStringTo(s, os);
}
#endif // GTEST_HAS_GLOBAL_WSTRING
#if GTEST_HAS_STD_WSTRING
GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
PrintWideStringTo(s, os);
}
#endif // GTEST_HAS_STD_WSTRING
#if GTEST_HAS_TR1_TUPLE
// Overload for ::std::tr1::tuple. Needed for printing function arguments,
// which are packed as tuples.
// Helper function for printing a tuple. T must be instantiated with
// a tuple type.
template <typename T>
void PrintTupleTo(const T& t, ::std::ostream* os);
// Overloaded PrintTo() for tuples of various arities. We support
// tuples of up-to 10 fields. The following implementation works
// regardless of whether tr1::tuple is implemented using the
// non-standard variadic template feature or not.
inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1>
void PrintTo(const ::std::tr1::tuple<T1>& t, ::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2>
void PrintTo(const ::std::tr1::tuple<T1, T2>& t, ::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3>
void PrintTo(const ::std::tr1::tuple<T1, T2, T3>& t, ::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3, typename T4>
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4>& t, ::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5>
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5>& t,
::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6>
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6>& t,
::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7>
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7>& t,
::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8>
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8>& t,
::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9>
void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>& t,
::std::ostream* os) {
PrintTupleTo(t, os);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9, typename T10>
void PrintTo(
const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& t,
::std::ostream* os) {
PrintTupleTo(t, os);
}
#endif // GTEST_HAS_TR1_TUPLE
// Overload for std::pair.
template <typename T1, typename T2>
void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
*os << '(';
// We cannot use UniversalPrint(value.first, os) here, as T1 may be
// a reference type. The same for printing value.second.
UniversalPrinter<T1>::Print(value.first, os);
*os << ", ";
UniversalPrinter<T2>::Print(value.second, os);
*os << ')';
}
// Implements printing a non-reference type T by letting the compiler
// pick the right overload of PrintTo() for T.
template <typename T>
class UniversalPrinter {
public:
// MSVC warns about adding const to a function type, so we want to
// disable the warning.
#ifdef _MSC_VER
# pragma warning(push) // Saves the current warning state.
# pragma warning(disable:4180) // Temporarily disables warning 4180.
#endif // _MSC_VER
// Note: we deliberately don't call this PrintTo(), as that name
// conflicts with ::testing::internal::PrintTo in the body of the
// function.
static void Print(const T& value, ::std::ostream* os) {
// By default, ::testing::internal::PrintTo() is used for printing
// the value.
//
// Thanks to Koenig look-up, if T is a class and has its own
// PrintTo() function defined in its namespace, that function will
// be visible here. Since it is more specific than the generic ones
// in ::testing::internal, it will be picked by the compiler in the
// following statement - exactly what we want.
PrintTo(value, os);
}
#ifdef _MSC_VER
# pragma warning(pop) // Restores the warning state.
#endif // _MSC_VER
};
// UniversalPrintArray(begin, len, os) prints an array of 'len'
// elements, starting at address 'begin'.
template <typename T>
void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
if (len == 0) {
*os << "{}";
} else {
*os << "{ ";
const size_t kThreshold = 18;
const size_t kChunkSize = 8;
// If the array has more than kThreshold elements, we'll have to
// omit some details by printing only the first and the last
// kChunkSize elements.
// TODO(wan@google.com): let the user control the threshold using a flag.
if (len <= kThreshold) {
PrintRawArrayTo(begin, len, os);
} else {
PrintRawArrayTo(begin, kChunkSize, os);
*os << ", ..., ";
PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
}
*os << " }";
}
}
// This overload prints a (const) char array compactly.
GTEST_API_ void UniversalPrintArray(
const char* begin, size_t len, ::std::ostream* os);
// This overload prints a (const) wchar_t array compactly.
GTEST_API_ void UniversalPrintArray(
const wchar_t* begin, size_t len, ::std::ostream* os);
// Implements printing an array type T[N].
template <typename T, size_t N>
class UniversalPrinter<T[N]> {
public:
// Prints the given array, omitting some elements when there are too
// many.
static void Print(const T (&a)[N], ::std::ostream* os) {
UniversalPrintArray(a, N, os);
}
};
// Implements printing a reference type T&.
template <typename T>
class UniversalPrinter<T&> {
public:
// MSVC warns about adding const to a function type, so we want to
// disable the warning.
#ifdef _MSC_VER
# pragma warning(push) // Saves the current warning state.
# pragma warning(disable:4180) // Temporarily disables warning 4180.
#endif // _MSC_VER
static void Print(const T& value, ::std::ostream* os) {
// Prints the address of the value. We use reinterpret_cast here
// as static_cast doesn't compile when T is a function type.
*os << "@" << reinterpret_cast<const void*>(&value) << " ";
// Then prints the value itself.
UniversalPrint(value, os);
}
#ifdef _MSC_VER
# pragma warning(pop) // Restores the warning state.
#endif // _MSC_VER
};
// Prints a value tersely: for a reference type, the referenced value
// (but not the address) is printed; for a (const) char pointer, the
// NUL-terminated string (but not the pointer) is printed.
template <typename T>
class UniversalTersePrinter {
public:
static void Print(const T& value, ::std::ostream* os) {
UniversalPrint(value, os);
}
};
template <typename T>
class UniversalTersePrinter<T&> {
public:
static void Print(const T& value, ::std::ostream* os) {
UniversalPrint(value, os);
}
};
template <typename T, size_t N>
class UniversalTersePrinter<T[N]> {
public:
static void Print(const T (&value)[N], ::std::ostream* os) {
UniversalPrinter<T[N]>::Print(value, os);
}
};
template <>
class UniversalTersePrinter<const char*> {
public:
static void Print(const char* str, ::std::ostream* os) {
if (str == NULL) {
*os << "NULL";
} else {
UniversalPrint(string(str), os);
}
}
};
template <>
class UniversalTersePrinter<char*> {
public:
static void Print(char* str, ::std::ostream* os) {
UniversalTersePrinter<const char*>::Print(str, os);
}
};
#if GTEST_HAS_STD_WSTRING
template <>
class UniversalTersePrinter<const wchar_t*> {
public:
static void Print(const wchar_t* str, ::std::ostream* os) {
if (str == NULL) {
*os << "NULL";
} else {
UniversalPrint(::std::wstring(str), os);
}
}
};
#endif
template <>
class UniversalTersePrinter<wchar_t*> {
public:
static void Print(wchar_t* str, ::std::ostream* os) {
UniversalTersePrinter<const wchar_t*>::Print(str, os);
}
};
template <typename T>
void UniversalTersePrint(const T& value, ::std::ostream* os) {
UniversalTersePrinter<T>::Print(value, os);
}
// Prints a value using the type inferred by the compiler. The
// difference between this and UniversalTersePrint() is that for a
// (const) char pointer, this prints both the pointer and the
// NUL-terminated string.
template <typename T>
void UniversalPrint(const T& value, ::std::ostream* os) {
// A workarond for the bug in VC++ 7.1 that prevents us from instantiating
// UniversalPrinter with T directly.
typedef T T1;
UniversalPrinter<T1>::Print(value, os);
}
#if GTEST_HAS_TR1_TUPLE
typedef ::std::vector<string> Strings;
// This helper template allows PrintTo() for tuples and
// UniversalTersePrintTupleFieldsToStrings() to be defined by
// induction on the number of tuple fields. The idea is that
// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
// fields in tuple t, and can be defined in terms of
// TuplePrefixPrinter<N - 1>.
// The inductive case.
template <size_t N>
struct TuplePrefixPrinter {
// Prints the first N fields of a tuple.
template <typename Tuple>
static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
*os << ", ";
UniversalPrinter<typename ::std::tr1::tuple_element<N - 1, Tuple>::type>
::Print(::std::tr1::get<N - 1>(t), os);
}
// Tersely prints the first N fields of a tuple to a string vector,
// one element for each field.
template <typename Tuple>
static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
::std::stringstream ss;
UniversalTersePrint(::std::tr1::get<N - 1>(t), &ss);
strings->push_back(ss.str());
}
};
// Base cases.
template <>
struct TuplePrefixPrinter<0> {
template <typename Tuple>
static void PrintPrefixTo(const Tuple&, ::std::ostream*) {}
template <typename Tuple>
static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
};
// We have to specialize the entire TuplePrefixPrinter<> class
// template here, even though the definition of
// TersePrintPrefixToStrings() is the same as the generic version, as
// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't
// support specializing a method template of a class template.
template <>
struct TuplePrefixPrinter<1> {
template <typename Tuple>
static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
UniversalPrinter<typename ::std::tr1::tuple_element<0, Tuple>::type>::
Print(::std::tr1::get<0>(t), os);
}
template <typename Tuple>
static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
::std::stringstream ss;
UniversalTersePrint(::std::tr1::get<0>(t), &ss);
strings->push_back(ss.str());
}
};
// Helper function for printing a tuple. T must be instantiated with
// a tuple type.
template <typename T>
void PrintTupleTo(const T& t, ::std::ostream* os) {
*os << "(";
TuplePrefixPrinter< ::std::tr1::tuple_size<T>::value>::
PrintPrefixTo(t, os);
*os << ")";
}
// Prints the fields of a tuple tersely to a string vector, one
// element for each field. See the comment before
// UniversalTersePrint() for how we define "tersely".
template <typename Tuple>
Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
Strings result;
TuplePrefixPrinter< ::std::tr1::tuple_size<Tuple>::value>::
TersePrintPrefixToStrings(value, &result);
return result;
}
#endif // GTEST_HAS_TR1_TUPLE
} // namespace internal
template <typename T>
::std::string PrintToString(const T& value) {
::std::stringstream ss;
internal::UniversalTersePrinter<T>::Print(value, &ss);
return ss.str();
}
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_

View file

@ -1,232 +0,0 @@
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
//
// Utilities for testing Google Test itself and code that uses Google Test
// (e.g. frameworks built on top of Google Test).
#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
#include "gtest/gtest.h"
namespace testing {
// This helper class can be used to mock out Google Test failure reporting
// so that we can test Google Test or code that builds on Google Test.
//
// An object of this class appends a TestPartResult object to the
// TestPartResultArray object given in the constructor whenever a Google Test
// failure is reported. It can either intercept only failures that are
// generated in the same thread that created this object or it can intercept
// all generated failures. The scope of this mock object can be controlled with
// the second argument to the two arguments constructor.
class GTEST_API_ ScopedFakeTestPartResultReporter
: public TestPartResultReporterInterface {
public:
// The two possible mocking modes of this object.
enum InterceptMode {
INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures.
INTERCEPT_ALL_THREADS // Intercepts all failures.
};
// The c'tor sets this object as the test part result reporter used
// by Google Test. The 'result' parameter specifies where to report the
// results. This reporter will only catch failures generated in the current
// thread. DEPRECATED
explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
// Same as above, but you can choose the interception scope of this object.
ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
TestPartResultArray* result);
// The d'tor restores the previous test part result reporter.
virtual ~ScopedFakeTestPartResultReporter();
// Appends the TestPartResult object to the TestPartResultArray
// received in the constructor.
//
// This method is from the TestPartResultReporterInterface
// interface.
virtual void ReportTestPartResult(const TestPartResult& result);
private:
void Init();
const InterceptMode intercept_mode_;
TestPartResultReporterInterface* old_reporter_;
TestPartResultArray* const result_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
};
namespace internal {
// A helper class for implementing EXPECT_FATAL_FAILURE() and
// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given
// TestPartResultArray contains exactly one failure that has the given
// type and contains the given substring. If that's not the case, a
// non-fatal failure will be generated.
class GTEST_API_ SingleFailureChecker {
public:
// The constructor remembers the arguments.
SingleFailureChecker(const TestPartResultArray* results,
TestPartResult::Type type,
const string& substr);
~SingleFailureChecker();
private:
const TestPartResultArray* const results_;
const TestPartResult::Type type_;
const string substr_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
};
} // namespace internal
} // namespace testing
// A set of macros for testing Google Test assertions or code that's expected
// to generate Google Test fatal failures. It verifies that the given
// statement will cause exactly one fatal Google Test failure with 'substr'
// being part of the failure message.
//
// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
// affects and considers failures generated in the current thread and
// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
//
// The verification of the assertion is done correctly even when the statement
// throws an exception or aborts the current function.
//
// Known restrictions:
// - 'statement' cannot reference local non-static variables or
// non-static members of the current object.
// - 'statement' cannot return a value.
// - You cannot stream a failure message to this macro.
//
// Note that even though the implementations of the following two
// macros are much alike, we cannot refactor them to use a common
// helper macro, due to some peculiarity in how the preprocessor
// works. The AcceptsMacroThatExpandsToUnprotectedComma test in
// gtest_unittest.cc will fail to compile if we do that.
#define EXPECT_FATAL_FAILURE(statement, substr) \
do { \
class GTestExpectFatalFailureHelper {\
public:\
static void Execute() { statement; }\
};\
::testing::TestPartResultArray gtest_failures;\
::testing::internal::SingleFailureChecker gtest_checker(\
&gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
{\
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
::testing::ScopedFakeTestPartResultReporter:: \
INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
GTestExpectFatalFailureHelper::Execute();\
}\
} while (::testing::internal::AlwaysFalse())
#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
do { \
class GTestExpectFatalFailureHelper {\
public:\
static void Execute() { statement; }\
};\
::testing::TestPartResultArray gtest_failures;\
::testing::internal::SingleFailureChecker gtest_checker(\
&gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
{\
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
::testing::ScopedFakeTestPartResultReporter:: \
INTERCEPT_ALL_THREADS, &gtest_failures);\
GTestExpectFatalFailureHelper::Execute();\
}\
} while (::testing::internal::AlwaysFalse())
// A macro for testing Google Test assertions or code that's expected to
// generate Google Test non-fatal failures. It asserts that the given
// statement will cause exactly one non-fatal Google Test failure with 'substr'
// being part of the failure message.
//
// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
// affects and considers failures generated in the current thread and
// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
//
// 'statement' is allowed to reference local variables and members of
// the current object.
//
// The verification of the assertion is done correctly even when the statement
// throws an exception or aborts the current function.
//
// Known restrictions:
// - You cannot stream a failure message to this macro.
//
// Note that even though the implementations of the following two
// macros are much alike, we cannot refactor them to use a common
// helper macro, due to some peculiarity in how the preprocessor
// works. If we do that, the code won't compile when the user gives
// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
// expands to code containing an unprotected comma. The
// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
// catches that.
//
// For the same reason, we have to write
// if (::testing::internal::AlwaysTrue()) { statement; }
// instead of
// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
// to avoid an MSVC warning on unreachable code.
#define EXPECT_NONFATAL_FAILURE(statement, substr) \
do {\
::testing::TestPartResultArray gtest_failures;\
::testing::internal::SingleFailureChecker gtest_checker(\
&gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
(substr));\
{\
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
::testing::ScopedFakeTestPartResultReporter:: \
INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
if (::testing::internal::AlwaysTrue()) { statement; }\
}\
} while (::testing::internal::AlwaysFalse())
#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
do {\
::testing::TestPartResultArray gtest_failures;\
::testing::internal::SingleFailureChecker gtest_checker(\
&gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
(substr));\
{\
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
&gtest_failures);\
if (::testing::internal::AlwaysTrue()) { statement; }\
}\
} while (::testing::internal::AlwaysFalse())
#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_

View file

@ -1,179 +0,0 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: mheule@google.com (Markus Heule)
//
#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
#include <iosfwd>
#include <vector>
#include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-string.h"
namespace testing {
// A copyable object representing the result of a test part (i.e. an
// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
//
// Don't inherit from TestPartResult as its destructor is not virtual.
class GTEST_API_ TestPartResult {
public:
// The possible outcomes of a test part (i.e. an assertion or an
// explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
enum Type {
kSuccess, // Succeeded.
kNonFatalFailure, // Failed but the test can continue.
kFatalFailure // Failed and the test should be terminated.
};
// C'tor. TestPartResult does NOT have a default constructor.
// Always use this constructor (with parameters) to create a
// TestPartResult object.
TestPartResult(Type a_type,
const char* a_file_name,
int a_line_number,
const char* a_message)
: type_(a_type),
file_name_(a_file_name == NULL ? "" : a_file_name),
line_number_(a_line_number),
summary_(ExtractSummary(a_message)),
message_(a_message) {
}
// Gets the outcome of the test part.
Type type() const { return type_; }
// Gets the name of the source file where the test part took place, or
// NULL if it's unknown.
const char* file_name() const {
return file_name_.empty() ? NULL : file_name_.c_str();
}
// Gets the line in the source file where the test part took place,
// or -1 if it's unknown.
int line_number() const { return line_number_; }
// Gets the summary of the failure message.
const char* summary() const { return summary_.c_str(); }
// Gets the message associated with the test part.
const char* message() const { return message_.c_str(); }
// Returns true iff the test part passed.
bool passed() const { return type_ == kSuccess; }
// Returns true iff the test part failed.
bool failed() const { return type_ != kSuccess; }
// Returns true iff the test part non-fatally failed.
bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
// Returns true iff the test part fatally failed.
bool fatally_failed() const { return type_ == kFatalFailure; }
private:
Type type_;
// Gets the summary of the failure message by omitting the stack
// trace in it.
static std::string ExtractSummary(const char* message);
// The name of the source file where the test part took place, or
// "" if the source file is unknown.
std::string file_name_;
// The line in the source file where the test part took place, or -1
// if the line number is unknown.
int line_number_;
std::string summary_; // The test failure summary.
std::string message_; // The test failure message.
};
// Prints a TestPartResult object.
std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
// An array of TestPartResult objects.
//
// Don't inherit from TestPartResultArray as its destructor is not
// virtual.
class GTEST_API_ TestPartResultArray {
public:
TestPartResultArray() {}
// Appends the given TestPartResult to the array.
void Append(const TestPartResult& result);
// Returns the TestPartResult at the given index (0-based).
const TestPartResult& GetTestPartResult(int index) const;
// Returns the number of TestPartResult objects in the array.
int size() const;
private:
std::vector<TestPartResult> array_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
};
// This interface knows how to report a test part result.
class TestPartResultReporterInterface {
public:
virtual ~TestPartResultReporterInterface() {}
virtual void ReportTestPartResult(const TestPartResult& result) = 0;
};
namespace internal {
// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
// statement generates new fatal failures. To do so it registers itself as the
// current test part result reporter. Besides checking if fatal failures were
// reported, it only delegates the reporting to the former result reporter.
// The original result reporter is restored in the destructor.
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
class GTEST_API_ HasNewFatalFailureHelper
: public TestPartResultReporterInterface {
public:
HasNewFatalFailureHelper();
virtual ~HasNewFatalFailureHelper();
virtual void ReportTestPartResult(const TestPartResult& result);
bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
private:
bool has_new_fatal_failure_;
TestPartResultReporterInterface* original_reporter_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
};
} // namespace internal
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_

View file

@ -1,259 +0,0 @@
// Copyright 2008 Google Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
// This header implements typed tests and type-parameterized tests.
// Typed (aka type-driven) tests repeat the same test for types in a
// list. You must know which types you want to test with when writing
// typed tests. Here's how you do it:
#if 0
// First, define a fixture class template. It should be parameterized
// by a type. Remember to derive it from testing::Test.
template <typename T>
class FooTest : public testing::Test {
public:
...
typedef std::list<T> List;
static T shared_;
T value_;
};
// Next, associate a list of types with the test case, which will be
// repeated for each type in the list. The typedef is necessary for
// the macro to parse correctly.
typedef testing::Types<char, int, unsigned int> MyTypes;
TYPED_TEST_CASE(FooTest, MyTypes);
// If the type list contains only one type, you can write that type
// directly without Types<...>:
// TYPED_TEST_CASE(FooTest, int);
// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
// tests for this test case as you want.
TYPED_TEST(FooTest, DoesBlah) {
// Inside a test, refer to TypeParam to get the type parameter.
// Since we are inside a derived class template, C++ requires use to
// visit the members of FooTest via 'this'.
TypeParam n = this->value_;
// To visit static members of the fixture, add the TestFixture::
// prefix.
n += TestFixture::shared_;
// To refer to typedefs in the fixture, add the "typename
// TestFixture::" prefix.
typename TestFixture::List values;
values.push_back(n);
...
}
TYPED_TEST(FooTest, HasPropertyA) { ... }
#endif // 0
// Type-parameterized tests are abstract test patterns parameterized
// by a type. Compared with typed tests, type-parameterized tests
// allow you to define the test pattern without knowing what the type
// parameters are. The defined pattern can be instantiated with
// different types any number of times, in any number of translation
// units.
//
// If you are designing an interface or concept, you can define a
// suite of type-parameterized tests to verify properties that any
// valid implementation of the interface/concept should have. Then,
// each implementation can easily instantiate the test suite to verify
// that it conforms to the requirements, without having to write
// similar tests repeatedly. Here's an example:
#if 0
// First, define a fixture class template. It should be parameterized
// by a type. Remember to derive it from testing::Test.
template <typename T>
class FooTest : public testing::Test {
...
};
// Next, declare that you will define a type-parameterized test case
// (the _P suffix is for "parameterized" or "pattern", whichever you
// prefer):
TYPED_TEST_CASE_P(FooTest);
// Then, use TYPED_TEST_P() to define as many type-parameterized tests
// for this type-parameterized test case as you want.
TYPED_TEST_P(FooTest, DoesBlah) {
// Inside a test, refer to TypeParam to get the type parameter.
TypeParam n = 0;
...
}
TYPED_TEST_P(FooTest, HasPropertyA) { ... }
// Now the tricky part: you need to register all test patterns before
// you can instantiate them. The first argument of the macro is the
// test case name; the rest are the names of the tests in this test
// case.
REGISTER_TYPED_TEST_CASE_P(FooTest,
DoesBlah, HasPropertyA);
// Finally, you are free to instantiate the pattern with the types you
// want. If you put the above code in a header file, you can #include
// it in multiple C++ source files and instantiate it multiple times.
//
// To distinguish different instances of the pattern, the first
// argument to the INSTANTIATE_* macro is a prefix that will be added
// to the actual test case name. Remember to pick unique prefixes for
// different instances.
typedef testing::Types<char, int, unsigned int> MyTypes;
INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
// If the type list contains only one type, you can write that type
// directly without Types<...>:
// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
#endif // 0
#include "gtest/internal/gtest-port.h"
#include "gtest/internal/gtest-type-util.h"
// Implements typed tests.
#if GTEST_HAS_TYPED_TEST
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Expands to the name of the typedef for the type parameters of the
// given test case.
# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
// The 'Types' template argument below must have spaces around it
// since some compilers may choke on '>>' when passing a template
// instance (e.g. Types<int>)
# define TYPED_TEST_CASE(CaseName, Types) \
typedef ::testing::internal::TypeList< Types >::type \
GTEST_TYPE_PARAMS_(CaseName)
# define TYPED_TEST(CaseName, TestName) \
template <typename gtest_TypeParam_> \
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
: public CaseName<gtest_TypeParam_> { \
private: \
typedef CaseName<gtest_TypeParam_> TestFixture; \
typedef gtest_TypeParam_ TypeParam; \
virtual void TestBody(); \
}; \
bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \
::testing::internal::TypeParameterizedTest< \
CaseName, \
::testing::internal::TemplateSel< \
GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \
GTEST_TYPE_PARAMS_(CaseName)>::Register(\
"", #CaseName, #TestName, 0); \
template <typename gtest_TypeParam_> \
void GTEST_TEST_CLASS_NAME_(CaseName, TestName)<gtest_TypeParam_>::TestBody()
#endif // GTEST_HAS_TYPED_TEST
// Implements type-parameterized tests.
#if GTEST_HAS_TYPED_TEST_P
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Expands to the namespace name that the type-parameterized tests for
// the given type-parameterized test case are defined in. The exact
// name of the namespace is subject to change without notice.
# define GTEST_CASE_NAMESPACE_(TestCaseName) \
gtest_case_##TestCaseName##_
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Expands to the name of the variable used to remember the names of
// the defined tests in the given test case.
# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
gtest_typed_test_case_p_state_##TestCaseName##_
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
//
// Expands to the name of the variable used to remember the names of
// the registered tests in the given test case.
# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
gtest_registered_test_names_##TestCaseName##_
// The variables defined in the type-parameterized test macros are
// static as typically these macros are used in a .h file that can be
// #included in multiple translation units linked together.
# define TYPED_TEST_CASE_P(CaseName) \
static ::testing::internal::TypedTestCasePState \
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
# define TYPED_TEST_P(CaseName, TestName) \
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
template <typename gtest_TypeParam_> \
class TestName : public CaseName<gtest_TypeParam_> { \
private: \
typedef CaseName<gtest_TypeParam_> TestFixture; \
typedef gtest_TypeParam_ TypeParam; \
virtual void TestBody(); \
}; \
static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
__FILE__, __LINE__, #CaseName, #TestName); \
} \
template <typename gtest_TypeParam_> \
void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
} \
static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
__FILE__, __LINE__, #__VA_ARGS__)
// The 'Types' template argument below must have spaces around it
// since some compilers may choke on '>>' when passing a template
// instance (e.g. Types<int>)
# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
::testing::internal::TypeParameterizedTestCase<CaseName, \
GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
::testing::internal::TypeList< Types >::type>::Register(\
#Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
#endif // GTEST_HAS_TYPED_TEST_P
#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_

File diff suppressed because it is too large Load diff

View file

@ -1,358 +0,0 @@
// Copyright 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This file is AUTOMATICALLY GENERATED on 10/31/2011 by command
// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
//
// Implements a family of generic predicate assertion macros.
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
// Makes sure this header is not included before gtest.h.
#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
# error Do not include gtest_pred_impl.h directly. Include gtest.h instead.
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
// This header implements a family of generic predicate assertion
// macros:
//
// ASSERT_PRED_FORMAT1(pred_format, v1)
// ASSERT_PRED_FORMAT2(pred_format, v1, v2)
// ...
//
// where pred_format is a function or functor that takes n (in the
// case of ASSERT_PRED_FORMATn) values and their source expression
// text, and returns a testing::AssertionResult. See the definition
// of ASSERT_EQ in gtest.h for an example.
//
// If you don't care about formatting, you can use the more
// restrictive version:
//
// ASSERT_PRED1(pred, v1)
// ASSERT_PRED2(pred, v1, v2)
// ...
//
// where pred is an n-ary function or functor that returns bool,
// and the values v1, v2, ..., must support the << operator for
// streaming to std::ostream.
//
// We also define the EXPECT_* variations.
//
// For now we only support predicates whose arity is at most 5.
// Please email googletestframework@googlegroups.com if you need
// support for higher arities.
// GTEST_ASSERT_ is the basic statement to which all of the assertions
// in this file reduce. Don't use this in your code.
#define GTEST_ASSERT_(expression, on_failure) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (const ::testing::AssertionResult gtest_ar = (expression)) \
; \
else \
on_failure(gtest_ar.failure_message())
// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use
// this in your code.
template <typename Pred,
typename T1>
AssertionResult AssertPred1Helper(const char* pred_text,
const char* e1,
Pred pred,
const T1& v1) {
if (pred(v1)) return AssertionSuccess();
return AssertionFailure() << pred_text << "("
<< e1 << ") evaluates to false, where"
<< "\n" << e1 << " evaluates to " << v1;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
// Don't use this in your code.
#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
GTEST_ASSERT_(pred_format(#v1, v1), \
on_failure)
// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use
// this in your code.
#define GTEST_PRED1_(pred, v1, on_failure)\
GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
#v1, \
pred, \
v1), on_failure)
// Unary predicate assertion macros.
#define EXPECT_PRED_FORMAT1(pred_format, v1) \
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
#define EXPECT_PRED1(pred, v1) \
GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
#define ASSERT_PRED_FORMAT1(pred_format, v1) \
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
#define ASSERT_PRED1(pred, v1) \
GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use
// this in your code.
template <typename Pred,
typename T1,
typename T2>
AssertionResult AssertPred2Helper(const char* pred_text,
const char* e1,
const char* e2,
Pred pred,
const T1& v1,
const T2& v2) {
if (pred(v1, v2)) return AssertionSuccess();
return AssertionFailure() << pred_text << "("
<< e1 << ", "
<< e2 << ") evaluates to false, where"
<< "\n" << e1 << " evaluates to " << v1
<< "\n" << e2 << " evaluates to " << v2;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
// Don't use this in your code.
#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \
on_failure)
// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use
// this in your code.
#define GTEST_PRED2_(pred, v1, v2, on_failure)\
GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
#v1, \
#v2, \
pred, \
v1, \
v2), on_failure)
// Binary predicate assertion macros.
#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
#define EXPECT_PRED2(pred, v1, v2) \
GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
#define ASSERT_PRED2(pred, v1, v2) \
GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use
// this in your code.
template <typename Pred,
typename T1,
typename T2,
typename T3>
AssertionResult AssertPred3Helper(const char* pred_text,
const char* e1,
const char* e2,
const char* e3,
Pred pred,
const T1& v1,
const T2& v2,
const T3& v3) {
if (pred(v1, v2, v3)) return AssertionSuccess();
return AssertionFailure() << pred_text << "("
<< e1 << ", "
<< e2 << ", "
<< e3 << ") evaluates to false, where"
<< "\n" << e1 << " evaluates to " << v1
<< "\n" << e2 << " evaluates to " << v2
<< "\n" << e3 << " evaluates to " << v3;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
// Don't use this in your code.
#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \
on_failure)
// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use
// this in your code.
#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
#v1, \
#v2, \
#v3, \
pred, \
v1, \
v2, \
v3), on_failure)
// Ternary predicate assertion macros.
#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
#define EXPECT_PRED3(pred, v1, v2, v3) \
GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
#define ASSERT_PRED3(pred, v1, v2, v3) \
GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use
// this in your code.
template <typename Pred,
typename T1,
typename T2,
typename T3,
typename T4>
AssertionResult AssertPred4Helper(const char* pred_text,
const char* e1,
const char* e2,
const char* e3,
const char* e4,
Pred pred,
const T1& v1,
const T2& v2,
const T3& v3,
const T4& v4) {
if (pred(v1, v2, v3, v4)) return AssertionSuccess();
return AssertionFailure() << pred_text << "("
<< e1 << ", "
<< e2 << ", "
<< e3 << ", "
<< e4 << ") evaluates to false, where"
<< "\n" << e1 << " evaluates to " << v1
<< "\n" << e2 << " evaluates to " << v2
<< "\n" << e3 << " evaluates to " << v3
<< "\n" << e4 << " evaluates to " << v4;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
// Don't use this in your code.
#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \
on_failure)
// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use
// this in your code.
#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
#v1, \
#v2, \
#v3, \
#v4, \
pred, \
v1, \
v2, \
v3, \
v4), on_failure)
// 4-ary predicate assertion macros.
#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use
// this in your code.
template <typename Pred,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
AssertionResult AssertPred5Helper(const char* pred_text,
const char* e1,
const char* e2,
const char* e3,
const char* e4,
const char* e5,
Pred pred,
const T1& v1,
const T2& v2,
const T3& v3,
const T4& v4,
const T5& v5) {
if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
return AssertionFailure() << pred_text << "("
<< e1 << ", "
<< e2 << ", "
<< e3 << ", "
<< e4 << ", "
<< e5 << ") evaluates to false, where"
<< "\n" << e1 << " evaluates to " << v1
<< "\n" << e2 << " evaluates to " << v2
<< "\n" << e3 << " evaluates to " << v3
<< "\n" << e4 << " evaluates to " << v4
<< "\n" << e5 << " evaluates to " << v5;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
// Don't use this in your code.
#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \
on_failure)
// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use
// this in your code.
#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
#v1, \
#v2, \
#v3, \
#v4, \
#v5, \
pred, \
v1, \
v2, \
v3, \
v4, \
v5), on_failure)
// 5-ary predicate assertion macros.
#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_

View file

@ -1,58 +0,0 @@
// Copyright 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
//
// Google C++ Testing Framework definitions useful in production code.
#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
// When you need to test the private or protected members of a class,
// use the FRIEND_TEST macro to declare your tests as friends of the
// class. For example:
//
// class MyClass {
// private:
// void MyMethod();
// FRIEND_TEST(MyClassTest, MyMethod);
// };
//
// class MyClassTest : public testing::Test {
// // ...
// };
//
// TEST_F(MyClassTest, MyMethod) {
// // Can call MyClass::MyMethod() here.
// }
#define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test
#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_

View file

@ -1,319 +0,0 @@
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
//
// The Google C++ Testing Framework (Google Test)
//
// This header file defines internal utilities needed for implementing
// death tests. They are subject to change without notice.
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
#include "gtest/internal/gtest-internal.h"
#include <stdio.h>
namespace testing {
namespace internal {
GTEST_DECLARE_string_(internal_run_death_test);
// Names of the flags (needed for parsing Google Test flags).
const char kDeathTestStyleFlag[] = "death_test_style";
const char kDeathTestUseFork[] = "death_test_use_fork";
const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
#if GTEST_HAS_DEATH_TEST
// DeathTest is a class that hides much of the complexity of the
// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method
// returns a concrete class that depends on the prevailing death test
// style, as defined by the --gtest_death_test_style and/or
// --gtest_internal_run_death_test flags.
// In describing the results of death tests, these terms are used with
// the corresponding definitions:
//
// exit status: The integer exit information in the format specified
// by wait(2)
// exit code: The integer code passed to exit(3), _exit(2), or
// returned from main()
class GTEST_API_ DeathTest {
public:
// Create returns false if there was an error determining the
// appropriate action to take for the current death test; for example,
// if the gtest_death_test_style flag is set to an invalid value.
// The LastMessage method will return a more detailed message in that
// case. Otherwise, the DeathTest pointer pointed to by the "test"
// argument is set. If the death test should be skipped, the pointer
// is set to NULL; otherwise, it is set to the address of a new concrete
// DeathTest object that controls the execution of the current test.
static bool Create(const char* statement, const RE* regex,
const char* file, int line, DeathTest** test);
DeathTest();
virtual ~DeathTest() { }
// A helper class that aborts a death test when it's deleted.
class ReturnSentinel {
public:
explicit ReturnSentinel(DeathTest* test) : test_(test) { }
~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
private:
DeathTest* const test_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
} GTEST_ATTRIBUTE_UNUSED_;
// An enumeration of possible roles that may be taken when a death
// test is encountered. EXECUTE means that the death test logic should
// be executed immediately. OVERSEE means that the program should prepare
// the appropriate environment for a child process to execute the death
// test, then wait for it to complete.
enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
// An enumeration of the three reasons that a test might be aborted.
enum AbortReason {
TEST_ENCOUNTERED_RETURN_STATEMENT,
TEST_THREW_EXCEPTION,
TEST_DID_NOT_DIE
};
// Assumes one of the above roles.
virtual TestRole AssumeRole() = 0;
// Waits for the death test to finish and returns its status.
virtual int Wait() = 0;
// Returns true if the death test passed; that is, the test process
// exited during the test, its exit status matches a user-supplied
// predicate, and its stderr output matches a user-supplied regular
// expression.
// The user-supplied predicate may be a macro expression rather
// than a function pointer or functor, or else Wait and Passed could
// be combined.
virtual bool Passed(bool exit_status_ok) = 0;
// Signals that the death test did not die as expected.
virtual void Abort(AbortReason reason) = 0;
// Returns a human-readable outcome message regarding the outcome of
// the last death test.
static const char* LastMessage();
static void set_last_death_test_message(const std::string& message);
private:
// A string containing a description of the outcome of the last death test.
static std::string last_death_test_message_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
};
// Factory interface for death tests. May be mocked out for testing.
class DeathTestFactory {
public:
virtual ~DeathTestFactory() { }
virtual bool Create(const char* statement, const RE* regex,
const char* file, int line, DeathTest** test) = 0;
};
// A concrete DeathTestFactory implementation for normal use.
class DefaultDeathTestFactory : public DeathTestFactory {
public:
virtual bool Create(const char* statement, const RE* regex,
const char* file, int line, DeathTest** test);
};
// Returns true if exit_status describes a process that was terminated
// by a signal, or exited normally with a nonzero exit code.
GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
// Traps C++ exceptions escaping statement and reports them as test
// failures. Note that trapping SEH exceptions is not implemented here.
# if GTEST_HAS_EXCEPTIONS
# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} catch (const ::std::exception& gtest_exception) { \
fprintf(\
stderr, \
"\n%s: Caught std::exception-derived exception escaping the " \
"death test statement. Exception message: %s\n", \
::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
gtest_exception.what()); \
fflush(stderr); \
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
} catch (...) { \
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
}
# else
# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
# endif
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
// ASSERT_EXIT*, and EXPECT_EXIT*.
# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
const ::testing::internal::RE& gtest_regex = (regex); \
::testing::internal::DeathTest* gtest_dt; \
if (!::testing::internal::DeathTest::Create(#statement, &gtest_regex, \
__FILE__, __LINE__, &gtest_dt)) { \
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
} \
if (gtest_dt != NULL) { \
::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \
gtest_dt_ptr(gtest_dt); \
switch (gtest_dt->AssumeRole()) { \
case ::testing::internal::DeathTest::OVERSEE_TEST: \
if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
} \
break; \
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
::testing::internal::DeathTest::ReturnSentinel \
gtest_sentinel(gtest_dt); \
GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
break; \
} \
default: \
break; \
} \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \
fail(::testing::internal::DeathTest::LastMessage())
// The symbol "fail" here expands to something into which a message
// can be streamed.
// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in
// NDEBUG mode. In this case we need the statements to be executed, the regex is
// ignored, and the macro must accept a streamed message even though the message
// is never printed.
# define GTEST_EXECUTE_STATEMENT_(statement, regex) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} else \
::testing::Message()
// A class representing the parsed contents of the
// --gtest_internal_run_death_test flag, as it existed when
// RUN_ALL_TESTS was called.
class InternalRunDeathTestFlag {
public:
InternalRunDeathTestFlag(const std::string& a_file,
int a_line,
int an_index,
int a_write_fd)
: file_(a_file), line_(a_line), index_(an_index),
write_fd_(a_write_fd) {}
~InternalRunDeathTestFlag() {
if (write_fd_ >= 0)
posix::Close(write_fd_);
}
const std::string& file() const { return file_; }
int line() const { return line_; }
int index() const { return index_; }
int write_fd() const { return write_fd_; }
private:
std::string file_;
int line_;
int index_;
int write_fd_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
};
// Returns a newly created InternalRunDeathTestFlag object with fields
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
// the flag is specified; otherwise returns NULL.
InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
#else // GTEST_HAS_DEATH_TEST
// This macro is used for implementing macros such as
// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
// death tests are not supported. Those macros must compile on such systems
// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
// systems that support death tests. This allows one to write such a macro
// on a system that does not support death tests and be sure that it will
// compile on a death-test supporting system.
//
// Parameters:
// statement - A statement that a macro such as EXPECT_DEATH would test
// for program termination. This macro has to make sure this
// statement is compiled but not executed, to ensure that
// EXPECT_DEATH_IF_SUPPORTED compiles with a certain
// parameter iff EXPECT_DEATH compiles with it.
// regex - A regex that a macro such as EXPECT_DEATH would use to test
// the output of statement. This parameter has to be
// compiled but not evaluated by this macro, to ensure that
// this macro only accepts expressions that a macro such as
// EXPECT_DEATH would accept.
// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
// and a return statement for ASSERT_DEATH_IF_SUPPORTED.
// This ensures that ASSERT_DEATH_IF_SUPPORTED will not
// compile inside functions where ASSERT_DEATH doesn't
// compile.
//
// The branch that has an always false condition is used to ensure that
// statement and regex are compiled (and thus syntactically correct) but
// never executed. The unreachable code macro protects the terminator
// statement from generating an 'unreachable code' warning in case
// statement unconditionally returns or throws. The Message constructor at
// the end allows the syntax of streaming additional messages into the
// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
GTEST_LOG_(WARNING) \
<< "Death tests are not supported on this platform.\n" \
<< "Statement '" #statement "' cannot be verified."; \
} else if (::testing::internal::AlwaysFalse()) { \
::testing::internal::RE::PartialMatch(".*", (regex)); \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
terminator; \
} else \
::testing::Message()
#endif // GTEST_HAS_DEATH_TEST
} // namespace internal
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_

View file

@ -1,206 +0,0 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: keith.ray@gmail.com (Keith Ray)
//
// Google Test filepath utilities
//
// This header file declares classes and functions used internally by
// Google Test. They are subject to change without notice.
//
// This file is #included in <gtest/internal/gtest-internal.h>.
// Do not include this header file separately!
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
#include "gtest/internal/gtest-string.h"
namespace testing {
namespace internal {
// FilePath - a class for file and directory pathname manipulation which
// handles platform-specific conventions (like the pathname separator).
// Used for helper functions for naming files in a directory for xml output.
// Except for Set methods, all methods are const or static, which provides an
// "immutable value object" -- useful for peace of mind.
// A FilePath with a value ending in a path separator ("like/this/") represents
// a directory, otherwise it is assumed to represent a file. In either case,
// it may or may not represent an actual file or directory in the file system.
// Names are NOT checked for syntax correctness -- no checking for illegal
// characters, malformed paths, etc.
class GTEST_API_ FilePath {
public:
FilePath() : pathname_("") { }
FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
explicit FilePath(const std::string& pathname) : pathname_(pathname) {
Normalize();
}
FilePath& operator=(const FilePath& rhs) {
Set(rhs);
return *this;
}
void Set(const FilePath& rhs) {
pathname_ = rhs.pathname_;
}
const std::string& string() const { return pathname_; }
const char* c_str() const { return pathname_.c_str(); }
// Returns the current working directory, or "" if unsuccessful.
static FilePath GetCurrentDir();
// Given directory = "dir", base_name = "test", number = 0,
// extension = "xml", returns "dir/test.xml". If number is greater
// than zero (e.g., 12), returns "dir/test_12.xml".
// On Windows platform, uses \ as the separator rather than /.
static FilePath MakeFileName(const FilePath& directory,
const FilePath& base_name,
int number,
const char* extension);
// Given directory = "dir", relative_path = "test.xml",
// returns "dir/test.xml".
// On Windows, uses \ as the separator rather than /.
static FilePath ConcatPaths(const FilePath& directory,
const FilePath& relative_path);
// Returns a pathname for a file that does not currently exist. The pathname
// will be directory/base_name.extension or
// directory/base_name_<number>.extension if directory/base_name.extension
// already exists. The number will be incremented until a pathname is found
// that does not already exist.
// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
// There could be a race condition if two or more processes are calling this
// function at the same time -- they could both pick the same filename.
static FilePath GenerateUniqueFileName(const FilePath& directory,
const FilePath& base_name,
const char* extension);
// Returns true iff the path is "".
bool IsEmpty() const { return pathname_.empty(); }
// If input name has a trailing separator character, removes it and returns
// the name, otherwise return the name string unmodified.
// On Windows platform, uses \ as the separator, other platforms use /.
FilePath RemoveTrailingPathSeparator() const;
// Returns a copy of the FilePath with the directory part removed.
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
// the FilePath unmodified. If there is no file part ("just_a_dir/") it
// returns an empty FilePath ("").
// On Windows platform, '\' is the path separator, otherwise it is '/'.
FilePath RemoveDirectoryName() const;
// RemoveFileName returns the directory path with the filename removed.
// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
// On Windows platform, '\' is the path separator, otherwise it is '/'.
FilePath RemoveFileName() const;
// Returns a copy of the FilePath with the case-insensitive extension removed.
// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
// FilePath("dir/file"). If a case-insensitive extension is not
// found, returns a copy of the original FilePath.
FilePath RemoveExtension(const char* extension) const;
// Creates directories so that path exists. Returns true if successful or if
// the directories already exist; returns false if unable to create
// directories for any reason. Will also return false if the FilePath does
// not represent a directory (that is, it doesn't end with a path separator).
bool CreateDirectoriesRecursively() const;
// Create the directory so that path exists. Returns true if successful or
// if the directory already exists; returns false if unable to create the
// directory for any reason, including if the parent directory does not
// exist. Not named "CreateDirectory" because that's a macro on Windows.
bool CreateFolder() const;
// Returns true if FilePath describes something in the file-system,
// either a file, directory, or whatever, and that something exists.
bool FileOrDirectoryExists() const;
// Returns true if pathname describes a directory in the file-system
// that exists.
bool DirectoryExists() const;
// Returns true if FilePath ends with a path separator, which indicates that
// it is intended to represent a directory. Returns false otherwise.
// This does NOT check that a directory (or file) actually exists.
bool IsDirectory() const;
// Returns true if pathname describes a root directory. (Windows has one
// root directory per disk drive.)
bool IsRootDirectory() const;
// Returns true if pathname describes an absolute path.
bool IsAbsolutePath() const;
private:
// Replaces multiple consecutive separators with a single separator.
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
// redundancies that might be in a pathname involving "." or "..".
//
// A pathname with multiple consecutive separators may occur either through
// user error or as a result of some scripts or APIs that generate a pathname
// with a trailing separator. On other platforms the same API or script
// may NOT generate a pathname with a trailing "/". Then elsewhere that
// pathname may have another "/" and pathname components added to it,
// without checking for the separator already being there.
// The script language and operating system may allow paths like "foo//bar"
// but some of the functions in FilePath will not handle that correctly. In
// particular, RemoveTrailingPathSeparator() only removes one separator, and
// it is called in CreateDirectoriesRecursively() assuming that it will change
// a pathname from directory syntax (trailing separator) to filename syntax.
//
// On Windows this method also replaces the alternate path separator '/' with
// the primary path separator '\\', so that for example "bar\\/\\foo" becomes
// "bar\\foo".
void Normalize();
// Returns a pointer to the last occurence of a valid path separator in
// the FilePath. On Windows, for example, both '/' and '\' are valid path
// separators. Returns NULL if no path separator was found.
const char* FindLastPathSeparator() const;
std::string pathname_;
}; // class FilePath
} // namespace internal
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_

File diff suppressed because it is too large Load diff

View file

@ -1,233 +0,0 @@
// Copyright 2003 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: Dan Egnor (egnor@google.com)
//
// A "smart" pointer type with reference tracking. Every pointer to a
// particular object is kept on a circular linked list. When the last pointer
// to an object is destroyed or reassigned, the object is deleted.
//
// Used properly, this deletes the object when the last reference goes away.
// There are several caveats:
// - Like all reference counting schemes, cycles lead to leaks.
// - Each smart pointer is actually two pointers (8 bytes instead of 4).
// - Every time a pointer is assigned, the entire list of pointers to that
// object is traversed. This class is therefore NOT SUITABLE when there
// will often be more than two or three pointers to a particular object.
// - References are only tracked as long as linked_ptr<> objects are copied.
// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS
// will happen (double deletion).
//
// A good use of this class is storing object references in STL containers.
// You can safely put linked_ptr<> in a vector<>.
// Other uses may not be as good.
//
// Note: If you use an incomplete type with linked_ptr<>, the class
// *containing* linked_ptr<> must have a constructor and destructor (even
// if they do nothing!).
//
// Bill Gibbons suggested we use something like this.
//
// Thread Safety:
// Unlike other linked_ptr implementations, in this implementation
// a linked_ptr object is thread-safe in the sense that:
// - it's safe to copy linked_ptr objects concurrently,
// - it's safe to copy *from* a linked_ptr and read its underlying
// raw pointer (e.g. via get()) concurrently, and
// - it's safe to write to two linked_ptrs that point to the same
// shared object concurrently.
// TODO(wan@google.com): rename this to safe_linked_ptr to avoid
// confusion with normal linked_ptr.
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
#include <stdlib.h>
#include <assert.h>
#include "gtest/internal/gtest-port.h"
namespace testing {
namespace internal {
// Protects copying of all linked_ptr objects.
GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
// This is used internally by all instances of linked_ptr<>. It needs to be
// a non-template class because different types of linked_ptr<> can refer to
// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)).
// So, it needs to be possible for different types of linked_ptr to participate
// in the same circular linked list, so we need a single class type here.
//
// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr<T>.
class linked_ptr_internal {
public:
// Create a new circle that includes only this instance.
void join_new() {
next_ = this;
}
// Many linked_ptr operations may change p.link_ for some linked_ptr
// variable p in the same circle as this object. Therefore we need
// to prevent two such operations from occurring concurrently.
//
// Note that different types of linked_ptr objects can coexist in a
// circle (e.g. linked_ptr<Base>, linked_ptr<Derived1>, and
// linked_ptr<Derived2>). Therefore we must use a single mutex to
// protect all linked_ptr objects. This can create serious
// contention in production code, but is acceptable in a testing
// framework.
// Join an existing circle.
void join(linked_ptr_internal const* ptr)
GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
MutexLock lock(&g_linked_ptr_mutex);
linked_ptr_internal const* p = ptr;
while (p->next_ != ptr) p = p->next_;
p->next_ = this;
next_ = ptr;
}
// Leave whatever circle we're part of. Returns true if we were the
// last member of the circle. Once this is done, you can join() another.
bool depart()
GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
MutexLock lock(&g_linked_ptr_mutex);
if (next_ == this) return true;
linked_ptr_internal const* p = next_;
while (p->next_ != this) p = p->next_;
p->next_ = next_;
return false;
}
private:
mutable linked_ptr_internal const* next_;
};
template <typename T>
class linked_ptr {
public:
typedef T element_type;
// Take over ownership of a raw pointer. This should happen as soon as
// possible after the object is created.
explicit linked_ptr(T* ptr = NULL) { capture(ptr); }
~linked_ptr() { depart(); }
// Copy an existing linked_ptr<>, adding ourselves to the list of references.
template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); }
linked_ptr(linked_ptr const& ptr) { // NOLINT
assert(&ptr != this);
copy(&ptr);
}
// Assignment releases the old value and acquires the new.
template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) {
depart();
copy(&ptr);
return *this;
}
linked_ptr& operator=(linked_ptr const& ptr) {
if (&ptr != this) {
depart();
copy(&ptr);
}
return *this;
}
// Smart pointer members.
void reset(T* ptr = NULL) {
depart();
capture(ptr);
}
T* get() const { return value_; }
T* operator->() const { return value_; }
T& operator*() const { return *value_; }
bool operator==(T* p) const { return value_ == p; }
bool operator!=(T* p) const { return value_ != p; }
template <typename U>
bool operator==(linked_ptr<U> const& ptr) const {
return value_ == ptr.get();
}
template <typename U>
bool operator!=(linked_ptr<U> const& ptr) const {
return value_ != ptr.get();
}
private:
template <typename U>
friend class linked_ptr;
T* value_;
linked_ptr_internal link_;
void depart() {
if (link_.depart()) delete value_;
}
void capture(T* ptr) {
value_ = ptr;
link_.join_new();
}
template <typename U> void copy(linked_ptr<U> const* ptr) {
value_ = ptr->get();
if (value_)
link_.join(&ptr->link_);
else
link_.join_new();
}
};
template<typename T> inline
bool operator==(T* ptr, const linked_ptr<T>& x) {
return ptr == x.get();
}
template<typename T> inline
bool operator!=(T* ptr, const linked_ptr<T>& x) {
return ptr != x.get();
}
// A function to convert T* into linked_ptr<T>
// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
template <typename T>
linked_ptr<T> make_linked_ptr(T* ptr) {
return linked_ptr<T>(ptr);
}
} // namespace internal
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_

File diff suppressed because it is too large Load diff

View file

@ -1,301 +0,0 @@
$$ -*- mode: c++; -*-
$var n = 50 $$ Maximum length of Values arguments we want to support.
$var maxtuple = 10 $$ Maximum number of Combine arguments we want to support.
// Copyright 2008 Google Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: vladl@google.com (Vlad Losev)
// Type and function utilities for implementing parameterized tests.
// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
//
// Currently Google Test supports at most $n arguments in Values,
// and at most $maxtuple arguments in Combine. Please contact
// googletestframework@googlegroups.com if you need more.
// Please note that the number of arguments to Combine is limited
// by the maximum arity of the implementation of tr1::tuple which is
// currently set at $maxtuple.
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
#include "gtest/internal/gtest-param-util.h"
#include "gtest/internal/gtest-port.h"
#if GTEST_HAS_PARAM_TEST
namespace testing {
// Forward declarations of ValuesIn(), which is implemented in
// include/gtest/gtest-param-test.h.
template <typename ForwardIterator>
internal::ParamGenerator<
typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
ValuesIn(ForwardIterator begin, ForwardIterator end);
template <typename T, size_t N>
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
template <class Container>
internal::ParamGenerator<typename Container::value_type> ValuesIn(
const Container& container);
namespace internal {
// Used in the Values() function to provide polymorphic capabilities.
template <typename T1>
class ValueArray1 {
public:
explicit ValueArray1(T1 v1) : v1_(v1) {}
template <typename T>
operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
private:
// No implementation - assignment is unsupported.
void operator=(const ValueArray1& other);
const T1 v1_;
};
$range i 2..n
$for i [[
$range j 1..i
template <$for j, [[typename T$j]]>
class ValueArray$i {
public:
ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {}
template <typename T>
operator ParamGenerator<T>() const {
const T array[] = {$for j, [[static_cast<T>(v$(j)_)]]};
return ValuesIn(array);
}
private:
// No implementation - assignment is unsupported.
void operator=(const ValueArray$i& other);
$for j [[
const T$j v$(j)_;
]]
};
]]
# if GTEST_HAS_COMBINE
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Generates values from the Cartesian product of values produced
// by the argument generators.
//
$range i 2..maxtuple
$for i [[
$range j 1..i
$range k 2..i
template <$for j, [[typename T$j]]>
class CartesianProductGenerator$i
: public ParamGeneratorInterface< ::std::tr1::tuple<$for j, [[T$j]]> > {
public:
typedef ::std::tr1::tuple<$for j, [[T$j]]> ParamType;
CartesianProductGenerator$i($for j, [[const ParamGenerator<T$j>& g$j]])
: $for j, [[g$(j)_(g$j)]] {}
virtual ~CartesianProductGenerator$i() {}
virtual ParamIteratorInterface<ParamType>* Begin() const {
return new Iterator(this, $for j, [[g$(j)_, g$(j)_.begin()]]);
}
virtual ParamIteratorInterface<ParamType>* End() const {
return new Iterator(this, $for j, [[g$(j)_, g$(j)_.end()]]);
}
private:
class Iterator : public ParamIteratorInterface<ParamType> {
public:
Iterator(const ParamGeneratorInterface<ParamType>* base, $for j, [[
const ParamGenerator<T$j>& g$j,
const typename ParamGenerator<T$j>::iterator& current$(j)]])
: base_(base),
$for j, [[
begin$(j)_(g$j.begin()), end$(j)_(g$j.end()), current$(j)_(current$j)
]] {
ComputeCurrentValue();
}
virtual ~Iterator() {}
virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
return base_;
}
// Advance should not be called on beyond-of-range iterators
// so no component iterators must be beyond end of range, either.
virtual void Advance() {
assert(!AtEnd());
++current$(i)_;
$for k [[
if (current$(i+2-k)_ == end$(i+2-k)_) {
current$(i+2-k)_ = begin$(i+2-k)_;
++current$(i+2-k-1)_;
}
]]
ComputeCurrentValue();
}
virtual ParamIteratorInterface<ParamType>* Clone() const {
return new Iterator(*this);
}
virtual const ParamType* Current() const { return &current_value_; }
virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
// Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast.
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
<< "The program attempted to compare iterators "
<< "from different generators." << std::endl;
const Iterator* typed_other =
CheckedDowncastToActualType<const Iterator>(&other);
// We must report iterators equal if they both point beyond their
// respective ranges. That can happen in a variety of fashions,
// so we have to consult AtEnd().
return (AtEnd() && typed_other->AtEnd()) ||
($for j && [[
current$(j)_ == typed_other->current$(j)_
]]);
}
private:
Iterator(const Iterator& other)
: base_(other.base_), $for j, [[
begin$(j)_(other.begin$(j)_),
end$(j)_(other.end$(j)_),
current$(j)_(other.current$(j)_)
]] {
ComputeCurrentValue();
}
void ComputeCurrentValue() {
if (!AtEnd())
current_value_ = ParamType($for j, [[*current$(j)_]]);
}
bool AtEnd() const {
// We must report iterator past the end of the range when either of the
// component iterators has reached the end of its range.
return
$for j || [[
current$(j)_ == end$(j)_
]];
}
// No implementation - assignment is unsupported.
void operator=(const Iterator& other);
const ParamGeneratorInterface<ParamType>* const base_;
// begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
// current[i]_ is the actual traversing iterator.
$for j [[
const typename ParamGenerator<T$j>::iterator begin$(j)_;
const typename ParamGenerator<T$j>::iterator end$(j)_;
typename ParamGenerator<T$j>::iterator current$(j)_;
]]
ParamType current_value_;
}; // class CartesianProductGenerator$i::Iterator
// No implementation - assignment is unsupported.
void operator=(const CartesianProductGenerator$i& other);
$for j [[
const ParamGenerator<T$j> g$(j)_;
]]
}; // class CartesianProductGenerator$i
]]
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Helper classes providing Combine() with polymorphic features. They allow
// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
// convertible to U.
//
$range i 2..maxtuple
$for i [[
$range j 1..i
template <$for j, [[class Generator$j]]>
class CartesianProductHolder$i {
public:
CartesianProductHolder$i($for j, [[const Generator$j& g$j]])
: $for j, [[g$(j)_(g$j)]] {}
template <$for j, [[typename T$j]]>
operator ParamGenerator< ::std::tr1::tuple<$for j, [[T$j]]> >() const {
return ParamGenerator< ::std::tr1::tuple<$for j, [[T$j]]> >(
new CartesianProductGenerator$i<$for j, [[T$j]]>(
$for j,[[
static_cast<ParamGenerator<T$j> >(g$(j)_)
]]));
}
private:
// No implementation - assignment is unsupported.
void operator=(const CartesianProductHolder$i& other);
$for j [[
const Generator$j g$(j)_;
]]
}; // class CartesianProductHolder$i
]]
# endif // GTEST_HAS_COMBINE
} // namespace internal
} // namespace testing
#endif // GTEST_HAS_PARAM_TEST
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_

View file

@ -1,619 +0,0 @@
// Copyright 2008 Google Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: vladl@google.com (Vlad Losev)
// Type and function utilities for implementing parameterized tests.
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
#include <iterator>
#include <utility>
#include <vector>
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
#include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-linked_ptr.h"
#include "gtest/internal/gtest-port.h"
#include "gtest/gtest-printers.h"
#if GTEST_HAS_PARAM_TEST
namespace testing {
namespace internal {
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Outputs a message explaining invalid registration of different
// fixture class for the same test case. This may happen when
// TEST_P macro is used to define two tests with the same name
// but in different namespaces.
GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
const char* file, int line);
template <typename> class ParamGeneratorInterface;
template <typename> class ParamGenerator;
// Interface for iterating over elements provided by an implementation
// of ParamGeneratorInterface<T>.
template <typename T>
class ParamIteratorInterface {
public:
virtual ~ParamIteratorInterface() {}
// A pointer to the base generator instance.
// Used only for the purposes of iterator comparison
// to make sure that two iterators belong to the same generator.
virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
// Advances iterator to point to the next element
// provided by the generator. The caller is responsible
// for not calling Advance() on an iterator equal to
// BaseGenerator()->End().
virtual void Advance() = 0;
// Clones the iterator object. Used for implementing copy semantics
// of ParamIterator<T>.
virtual ParamIteratorInterface* Clone() const = 0;
// Dereferences the current iterator and provides (read-only) access
// to the pointed value. It is the caller's responsibility not to call
// Current() on an iterator equal to BaseGenerator()->End().
// Used for implementing ParamGenerator<T>::operator*().
virtual const T* Current() const = 0;
// Determines whether the given iterator and other point to the same
// element in the sequence generated by the generator.
// Used for implementing ParamGenerator<T>::operator==().
virtual bool Equals(const ParamIteratorInterface& other) const = 0;
};
// Class iterating over elements provided by an implementation of
// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
// and implements the const forward iterator concept.
template <typename T>
class ParamIterator {
public:
typedef T value_type;
typedef const T& reference;
typedef ptrdiff_t difference_type;
// ParamIterator assumes ownership of the impl_ pointer.
ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
ParamIterator& operator=(const ParamIterator& other) {
if (this != &other)
impl_.reset(other.impl_->Clone());
return *this;
}
const T& operator*() const { return *impl_->Current(); }
const T* operator->() const { return impl_->Current(); }
// Prefix version of operator++.
ParamIterator& operator++() {
impl_->Advance();
return *this;
}
// Postfix version of operator++.
ParamIterator operator++(int /*unused*/) {
ParamIteratorInterface<T>* clone = impl_->Clone();
impl_->Advance();
return ParamIterator(clone);
}
bool operator==(const ParamIterator& other) const {
return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
}
bool operator!=(const ParamIterator& other) const {
return !(*this == other);
}
private:
friend class ParamGenerator<T>;
explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
scoped_ptr<ParamIteratorInterface<T> > impl_;
};
// ParamGeneratorInterface<T> is the binary interface to access generators
// defined in other translation units.
template <typename T>
class ParamGeneratorInterface {
public:
typedef T ParamType;
virtual ~ParamGeneratorInterface() {}
// Generator interface definition
virtual ParamIteratorInterface<T>* Begin() const = 0;
virtual ParamIteratorInterface<T>* End() const = 0;
};
// Wraps ParamGeneratorInterface<T> and provides general generator syntax
// compatible with the STL Container concept.
// This class implements copy initialization semantics and the contained
// ParamGeneratorInterface<T> instance is shared among all copies
// of the original object. This is possible because that instance is immutable.
template<typename T>
class ParamGenerator {
public:
typedef ParamIterator<T> iterator;
explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
ParamGenerator& operator=(const ParamGenerator& other) {
impl_ = other.impl_;
return *this;
}
iterator begin() const { return iterator(impl_->Begin()); }
iterator end() const { return iterator(impl_->End()); }
private:
linked_ptr<const ParamGeneratorInterface<T> > impl_;
};
// Generates values from a range of two comparable values. Can be used to
// generate sequences of user-defined types that implement operator+() and
// operator<().
// This class is used in the Range() function.
template <typename T, typename IncrementT>
class RangeGenerator : public ParamGeneratorInterface<T> {
public:
RangeGenerator(T begin, T end, IncrementT step)
: begin_(begin), end_(end),
step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
virtual ~RangeGenerator() {}
virtual ParamIteratorInterface<T>* Begin() const {
return new Iterator(this, begin_, 0, step_);
}
virtual ParamIteratorInterface<T>* End() const {
return new Iterator(this, end_, end_index_, step_);
}
private:
class Iterator : public ParamIteratorInterface<T> {
public:
Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
IncrementT step)
: base_(base), value_(value), index_(index), step_(step) {}
virtual ~Iterator() {}
virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
return base_;
}
virtual void Advance() {
value_ = value_ + step_;
index_++;
}
virtual ParamIteratorInterface<T>* Clone() const {
return new Iterator(*this);
}
virtual const T* Current() const { return &value_; }
virtual bool Equals(const ParamIteratorInterface<T>& other) const {
// Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast.
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
<< "The program attempted to compare iterators "
<< "from different generators." << std::endl;
const int other_index =
CheckedDowncastToActualType<const Iterator>(&other)->index_;
return index_ == other_index;
}
private:
Iterator(const Iterator& other)
: ParamIteratorInterface<T>(),
base_(other.base_), value_(other.value_), index_(other.index_),
step_(other.step_) {}
// No implementation - assignment is unsupported.
void operator=(const Iterator& other);
const ParamGeneratorInterface<T>* const base_;
T value_;
int index_;
const IncrementT step_;
}; // class RangeGenerator::Iterator
static int CalculateEndIndex(const T& begin,
const T& end,
const IncrementT& step) {
int end_index = 0;
for (T i = begin; i < end; i = i + step)
end_index++;
return end_index;
}
// No implementation - assignment is unsupported.
void operator=(const RangeGenerator& other);
const T begin_;
const T end_;
const IncrementT step_;
// The index for the end() iterator. All the elements in the generated
// sequence are indexed (0-based) to aid iterator comparison.
const int end_index_;
}; // class RangeGenerator
// Generates values from a pair of STL-style iterators. Used in the
// ValuesIn() function. The elements are copied from the source range
// since the source can be located on the stack, and the generator
// is likely to persist beyond that stack frame.
template <typename T>
class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
public:
template <typename ForwardIterator>
ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
: container_(begin, end) {}
virtual ~ValuesInIteratorRangeGenerator() {}
virtual ParamIteratorInterface<T>* Begin() const {
return new Iterator(this, container_.begin());
}
virtual ParamIteratorInterface<T>* End() const {
return new Iterator(this, container_.end());
}
private:
typedef typename ::std::vector<T> ContainerType;
class Iterator : public ParamIteratorInterface<T> {
public:
Iterator(const ParamGeneratorInterface<T>* base,
typename ContainerType::const_iterator iterator)
: base_(base), iterator_(iterator) {}
virtual ~Iterator() {}
virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
return base_;
}
virtual void Advance() {
++iterator_;
value_.reset();
}
virtual ParamIteratorInterface<T>* Clone() const {
return new Iterator(*this);
}
// We need to use cached value referenced by iterator_ because *iterator_
// can return a temporary object (and of type other then T), so just
// having "return &*iterator_;" doesn't work.
// value_ is updated here and not in Advance() because Advance()
// can advance iterator_ beyond the end of the range, and we cannot
// detect that fact. The client code, on the other hand, is
// responsible for not calling Current() on an out-of-range iterator.
virtual const T* Current() const {
if (value_.get() == NULL)
value_.reset(new T(*iterator_));
return value_.get();
}
virtual bool Equals(const ParamIteratorInterface<T>& other) const {
// Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast.
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
<< "The program attempted to compare iterators "
<< "from different generators." << std::endl;
return iterator_ ==
CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
}
private:
Iterator(const Iterator& other)
// The explicit constructor call suppresses a false warning
// emitted by gcc when supplied with the -Wextra option.
: ParamIteratorInterface<T>(),
base_(other.base_),
iterator_(other.iterator_) {}
const ParamGeneratorInterface<T>* const base_;
typename ContainerType::const_iterator iterator_;
// A cached value of *iterator_. We keep it here to allow access by
// pointer in the wrapping iterator's operator->().
// value_ needs to be mutable to be accessed in Current().
// Use of scoped_ptr helps manage cached value's lifetime,
// which is bound by the lifespan of the iterator itself.
mutable scoped_ptr<const T> value_;
}; // class ValuesInIteratorRangeGenerator::Iterator
// No implementation - assignment is unsupported.
void operator=(const ValuesInIteratorRangeGenerator& other);
const ContainerType container_;
}; // class ValuesInIteratorRangeGenerator
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Stores a parameter value and later creates tests parameterized with that
// value.
template <class TestClass>
class ParameterizedTestFactory : public TestFactoryBase {
public:
typedef typename TestClass::ParamType ParamType;
explicit ParameterizedTestFactory(ParamType parameter) :
parameter_(parameter) {}
virtual Test* CreateTest() {
TestClass::SetParam(&parameter_);
return new TestClass();
}
private:
const ParamType parameter_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
};
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// TestMetaFactoryBase is a base class for meta-factories that create
// test factories for passing into MakeAndRegisterTestInfo function.
template <class ParamType>
class TestMetaFactoryBase {
public:
virtual ~TestMetaFactoryBase() {}
virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
};
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// TestMetaFactory creates test factories for passing into
// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
// ownership of test factory pointer, same factory object cannot be passed
// into that method twice. But ParameterizedTestCaseInfo is going to call
// it for each Test/Parameter value combination. Thus it needs meta factory
// creator class.
template <class TestCase>
class TestMetaFactory
: public TestMetaFactoryBase<typename TestCase::ParamType> {
public:
typedef typename TestCase::ParamType ParamType;
TestMetaFactory() {}
virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
return new ParameterizedTestFactory<TestCase>(parameter);
}
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
};
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// ParameterizedTestCaseInfoBase is a generic interface
// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase
// accumulates test information provided by TEST_P macro invocations
// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations
// and uses that information to register all resulting test instances
// in RegisterTests method. The ParameterizeTestCaseRegistry class holds
// a collection of pointers to the ParameterizedTestCaseInfo objects
// and calls RegisterTests() on each of them when asked.
class ParameterizedTestCaseInfoBase {
public:
virtual ~ParameterizedTestCaseInfoBase() {}
// Base part of test case name for display purposes.
virtual const string& GetTestCaseName() const = 0;
// Test case id to verify identity.
virtual TypeId GetTestCaseTypeId() const = 0;
// UnitTest class invokes this method to register tests in this
// test case right before running them in RUN_ALL_TESTS macro.
// This method should not be called more then once on any single
// instance of a ParameterizedTestCaseInfoBase derived class.
virtual void RegisterTests() = 0;
protected:
ParameterizedTestCaseInfoBase() {}
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
};
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P
// macro invocations for a particular test case and generators
// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that
// test case. It registers tests with all values generated by all
// generators when asked.
template <class TestCase>
class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
public:
// ParamType and GeneratorCreationFunc are private types but are required
// for declarations of public methods AddTestPattern() and
// AddTestCaseInstantiation().
typedef typename TestCase::ParamType ParamType;
// A function that returns an instance of appropriate generator type.
typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
explicit ParameterizedTestCaseInfo(const char* name)
: test_case_name_(name) {}
// Test case base name for display purposes.
virtual const string& GetTestCaseName() const { return test_case_name_; }
// Test case id to verify identity.
virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
// TEST_P macro uses AddTestPattern() to record information
// about a single test in a LocalTestInfo structure.
// test_case_name is the base name of the test case (without invocation
// prefix). test_base_name is the name of an individual test without
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
// test case base name and DoBar is test base name.
void AddTestPattern(const char* test_case_name,
const char* test_base_name,
TestMetaFactoryBase<ParamType>* meta_factory) {
tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
test_base_name,
meta_factory)));
}
// INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
// about a generator.
int AddTestCaseInstantiation(const string& instantiation_name,
GeneratorCreationFunc* func,
const char* /* file */,
int /* line */) {
instantiations_.push_back(::std::make_pair(instantiation_name, func));
return 0; // Return value used only to run this method in namespace scope.
}
// UnitTest class invokes this method to register tests in this test case
// test cases right before running tests in RUN_ALL_TESTS macro.
// This method should not be called more then once on any single
// instance of a ParameterizedTestCaseInfoBase derived class.
// UnitTest has a guard to prevent from calling this method more then once.
virtual void RegisterTests() {
for (typename TestInfoContainer::iterator test_it = tests_.begin();
test_it != tests_.end(); ++test_it) {
linked_ptr<TestInfo> test_info = *test_it;
for (typename InstantiationContainer::iterator gen_it =
instantiations_.begin(); gen_it != instantiations_.end();
++gen_it) {
const string& instantiation_name = gen_it->first;
ParamGenerator<ParamType> generator((*gen_it->second)());
string test_case_name;
if ( !instantiation_name.empty() )
test_case_name = instantiation_name + "/";
test_case_name += test_info->test_case_base_name;
int i = 0;
for (typename ParamGenerator<ParamType>::iterator param_it =
generator.begin();
param_it != generator.end(); ++param_it, ++i) {
Message test_name_stream;
test_name_stream << test_info->test_base_name << "/" << i;
MakeAndRegisterTestInfo(
test_case_name.c_str(),
test_name_stream.GetString().c_str(),
NULL, // No type parameter.
PrintToString(*param_it).c_str(),
GetTestCaseTypeId(),
TestCase::SetUpTestCase,
TestCase::TearDownTestCase,
test_info->test_meta_factory->CreateTestFactory(*param_it));
} // for param_it
} // for gen_it
} // for test_it
} // RegisterTests
private:
// LocalTestInfo structure keeps information about a single test registered
// with TEST_P macro.
struct TestInfo {
TestInfo(const char* a_test_case_base_name,
const char* a_test_base_name,
TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
test_case_base_name(a_test_case_base_name),
test_base_name(a_test_base_name),
test_meta_factory(a_test_meta_factory) {}
const string test_case_base_name;
const string test_base_name;
const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
};
typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
// Keeps pairs of <Instantiation name, Sequence generator creation function>
// received from INSTANTIATE_TEST_CASE_P macros.
typedef ::std::vector<std::pair<string, GeneratorCreationFunc*> >
InstantiationContainer;
const string test_case_name_;
TestInfoContainer tests_;
InstantiationContainer instantiations_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
}; // class ParameterizedTestCaseInfo
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase
// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P
// macros use it to locate their corresponding ParameterizedTestCaseInfo
// descriptors.
class ParameterizedTestCaseRegistry {
public:
ParameterizedTestCaseRegistry() {}
~ParameterizedTestCaseRegistry() {
for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
it != test_case_infos_.end(); ++it) {
delete *it;
}
}
// Looks up or creates and returns a structure containing information about
// tests and instantiations of a particular test case.
template <class TestCase>
ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
const char* test_case_name,
const char* file,
int line) {
ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
it != test_case_infos_.end(); ++it) {
if ((*it)->GetTestCaseName() == test_case_name) {
if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
// Complain about incorrect usage of Google Test facilities
// and terminate the program since we cannot guaranty correct
// test case setup and tear-down in this case.
ReportInvalidTestCaseType(test_case_name, file, line);
posix::Abort();
} else {
// At this point we are sure that the object we found is of the same
// type we are looking for, so we downcast it to that type
// without further checks.
typed_test_info = CheckedDowncastToActualType<
ParameterizedTestCaseInfo<TestCase> >(*it);
}
break;
}
}
if (typed_test_info == NULL) {
typed_test_info = new ParameterizedTestCaseInfo<TestCase>(test_case_name);
test_case_infos_.push_back(typed_test_info);
}
return typed_test_info;
}
void RegisterTests() {
for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
it != test_case_infos_.end(); ++it) {
(*it)->RegisterTests();
}
}
private:
typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
TestCaseInfoContainer test_case_infos_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
};
} // namespace internal
} // namespace testing
#endif // GTEST_HAS_PARAM_TEST
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_

File diff suppressed because it is too large Load diff

View file

@ -1,167 +0,0 @@
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
//
// The Google C++ Testing Framework (Google Test)
//
// This header file declares the String class and functions used internally by
// Google Test. They are subject to change without notice. They should not used
// by code external to Google Test.
//
// This header file is #included by <gtest/internal/gtest-internal.h>.
// It should not be #included by other files.
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
#ifdef __BORLANDC__
// string.h is not guaranteed to provide strcpy on C++ Builder.
# include <mem.h>
#endif
#include <string.h>
#include <string>
#include "gtest/internal/gtest-port.h"
namespace testing {
namespace internal {
// String - an abstract class holding static string utilities.
class GTEST_API_ String {
public:
// Static utility methods
// Clones a 0-terminated C string, allocating memory using new. The
// caller is responsible for deleting the return value using
// delete[]. Returns the cloned string, or NULL if the input is
// NULL.
//
// This is different from strdup() in string.h, which allocates
// memory using malloc().
static const char* CloneCString(const char* c_str);
#if GTEST_OS_WINDOWS_MOBILE
// Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
// able to pass strings to Win32 APIs on CE we need to convert them
// to 'Unicode', UTF-16.
// Creates a UTF-16 wide string from the given ANSI string, allocating
// memory using new. The caller is responsible for deleting the return
// value using delete[]. Returns the wide string, or NULL if the
// input is NULL.
//
// The wide string is created using the ANSI codepage (CP_ACP) to
// match the behaviour of the ANSI versions of Win32 calls and the
// C runtime.
static LPCWSTR AnsiToUtf16(const char* c_str);
// Creates an ANSI string from the given wide string, allocating
// memory using new. The caller is responsible for deleting the return
// value using delete[]. Returns the ANSI string, or NULL if the
// input is NULL.
//
// The returned string is created using the ANSI codepage (CP_ACP) to
// match the behaviour of the ANSI versions of Win32 calls and the
// C runtime.
static const char* Utf16ToAnsi(LPCWSTR utf16_str);
#endif
// Compares two C strings. Returns true iff they have the same content.
//
// Unlike strcmp(), this function can handle NULL argument(s). A
// NULL C string is considered different to any non-NULL C string,
// including the empty string.
static bool CStringEquals(const char* lhs, const char* rhs);
// Converts a wide C string to a String using the UTF-8 encoding.
// NULL will be converted to "(null)". If an error occurred during
// the conversion, "(failed to convert from wide string)" is
// returned.
static std::string ShowWideCString(const wchar_t* wide_c_str);
// Compares two wide C strings. Returns true iff they have the same
// content.
//
// Unlike wcscmp(), this function can handle NULL argument(s). A
// NULL C string is considered different to any non-NULL C string,
// including the empty string.
static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
// Compares two C strings, ignoring case. Returns true iff they
// have the same content.
//
// Unlike strcasecmp(), this function can handle NULL argument(s).
// A NULL C string is considered different to any non-NULL C string,
// including the empty string.
static bool CaseInsensitiveCStringEquals(const char* lhs,
const char* rhs);
// Compares two wide C strings, ignoring case. Returns true iff they
// have the same content.
//
// Unlike wcscasecmp(), this function can handle NULL argument(s).
// A NULL C string is considered different to any non-NULL wide C string,
// including the empty string.
// NB: The implementations on different platforms slightly differ.
// On windows, this method uses _wcsicmp which compares according to LC_CTYPE
// environment variable. On GNU platform this method uses wcscasecmp
// which compares according to LC_CTYPE category of the current locale.
// On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
// current locale.
static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
const wchar_t* rhs);
// Returns true iff the given string ends with the given suffix, ignoring
// case. Any string is considered to end with an empty suffix.
static bool EndsWithCaseInsensitive(
const std::string& str, const std::string& suffix);
// Formats an int value as "%02d".
static std::string FormatIntWidth2(int value); // "%02d" for width == 2
// Formats an int value as "%X".
static std::string FormatHexInt(int value);
// Formats a byte as "%02X".
static std::string FormatByte(unsigned char value);
private:
String(); // Not meant to be instantiated.
}; // class String
// Gets the content of the stringstream's buffer as an std::string. Each '\0'
// character in the buffer is replaced with "\\0".
GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
} // namespace internal
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_

File diff suppressed because it is too large Load diff

View file

@ -1,339 +0,0 @@
$$ -*- mode: c++; -*-
$var n = 10 $$ Maximum number of tuple fields we want to support.
$$ This meta comment fixes auto-indentation in Emacs. }}
// Copyright 2009 Google Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
#include <utility> // For ::std::pair.
// The compiler used in Symbian has a bug that prevents us from declaring the
// tuple template as a friend (it complains that tuple is redefined). This
// hack bypasses the bug by declaring the members that should otherwise be
// private as public.
// Sun Studio versions < 12 also have the above bug.
#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
#else
# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
template <GTEST_$(n)_TYPENAMES_(U)> friend class tuple; \
private:
#endif
$range i 0..n-1
$range j 0..n
$range k 1..n
// GTEST_n_TUPLE_(T) is the type of an n-tuple.
#define GTEST_0_TUPLE_(T) tuple<>
$for k [[
$range m 0..k-1
$range m2 k..n-1
#define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]>
]]
// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
$for j [[
$range m 0..j-1
#define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]]
]]
// In theory, defining stuff in the ::std namespace is undefined
// behavior. We can do this as we are playing the role of a standard
// library vendor.
namespace std {
namespace tr1 {
template <$for i, [[typename T$i = void]]>
class tuple;
// Anything in namespace gtest_internal is Google Test's INTERNAL
// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
namespace gtest_internal {
// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
template <typename T>
struct ByRef { typedef const T& type; }; // NOLINT
template <typename T>
struct ByRef<T&> { typedef T& type; }; // NOLINT
// A handy wrapper for ByRef.
#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
// AddRef<T>::type is T if T is a reference; otherwise it's T&. This
// is the same as tr1::add_reference<T>::type.
template <typename T>
struct AddRef { typedef T& type; }; // NOLINT
template <typename T>
struct AddRef<T&> { typedef T& type; }; // NOLINT
// A handy wrapper for AddRef.
#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
// A helper for implementing get<k>().
template <int k> class Get;
// A helper for implementing tuple_element<k, T>. kIndexValid is true
// iff k < the number of fields in tuple type T.
template <bool kIndexValid, int kIndex, class Tuple>
struct TupleElement;
$for i [[
template <GTEST_$(n)_TYPENAMES_(T)>
struct TupleElement<true, $i, GTEST_$(n)_TUPLE_(T) > {
typedef T$i type;
};
]]
} // namespace gtest_internal
template <>
class tuple<> {
public:
tuple() {}
tuple(const tuple& /* t */) {}
tuple& operator=(const tuple& /* t */) { return *this; }
};
$for k [[
$range m 0..k-1
template <GTEST_$(k)_TYPENAMES_(T)>
class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] {
public:
template <int k> friend class gtest_internal::Get;
tuple() : $for m, [[f$(m)_()]] {}
explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]]
$for m, [[f$(m)_(f$m)]] {}
tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
template <GTEST_$(k)_TYPENAMES_(U)>
tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {}
$if k == 2 [[
template <typename U0, typename U1>
tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
]]
tuple& operator=(const tuple& t) { return CopyFrom(t); }
template <GTEST_$(k)_TYPENAMES_(U)>
tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) {
return CopyFrom(t);
}
$if k == 2 [[
template <typename U0, typename U1>
tuple& operator=(const ::std::pair<U0, U1>& p) {
f0_ = p.first;
f1_ = p.second;
return *this;
}
]]
GTEST_DECLARE_TUPLE_AS_FRIEND_
template <GTEST_$(k)_TYPENAMES_(U)>
tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) {
$for m [[
f$(m)_ = t.f$(m)_;
]]
return *this;
}
$for m [[
T$m f$(m)_;
]]
};
]]
// 6.1.3.2 Tuple creation functions.
// Known limitations: we don't support passing an
// std::tr1::reference_wrapper<T> to make_tuple(). And we don't
// implement tie().
inline tuple<> make_tuple() { return tuple<>(); }
$for k [[
$range m 0..k-1
template <GTEST_$(k)_TYPENAMES_(T)>
inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) {
return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]);
}
]]
// 6.1.3.3 Tuple helper classes.
template <typename Tuple> struct tuple_size;
$for j [[
template <GTEST_$(j)_TYPENAMES_(T)>
struct tuple_size<GTEST_$(j)_TUPLE_(T) > {
static const int value = $j;
};
]]
template <int k, class Tuple>
struct tuple_element {
typedef typename gtest_internal::TupleElement<
k < (tuple_size<Tuple>::value), k, Tuple>::type type;
};
#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
// 6.1.3.4 Element access.
namespace gtest_internal {
$for i [[
template <>
class Get<$i> {
public:
template <class Tuple>
static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
Field(Tuple& t) { return t.f$(i)_; } // NOLINT
template <class Tuple>
static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple))
ConstField(const Tuple& t) { return t.f$(i)_; }
};
]]
} // namespace gtest_internal
template <int k, GTEST_$(n)_TYPENAMES_(T)>
GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
get(GTEST_$(n)_TUPLE_(T)& t) {
return gtest_internal::Get<k>::Field(t);
}
template <int k, GTEST_$(n)_TYPENAMES_(T)>
GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T)))
get(const GTEST_$(n)_TUPLE_(T)& t) {
return gtest_internal::Get<k>::ConstField(t);
}
// 6.1.3.5 Relational operators
// We only implement == and !=, as we don't have a need for the rest yet.
namespace gtest_internal {
// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
// first k fields of t1 equals the first k fields of t2.
// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
// k1 != k2.
template <int kSize1, int kSize2>
struct SameSizeTuplePrefixComparator;
template <>
struct SameSizeTuplePrefixComparator<0, 0> {
template <class Tuple1, class Tuple2>
static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
return true;
}
};
template <int k>
struct SameSizeTuplePrefixComparator<k, k> {
template <class Tuple1, class Tuple2>
static bool Eq(const Tuple1& t1, const Tuple2& t2) {
return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
}
};
} // namespace gtest_internal
template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t,
const GTEST_$(n)_TUPLE_(U)& u) {
return gtest_internal::SameSizeTuplePrefixComparator<
tuple_size<GTEST_$(n)_TUPLE_(T) >::value,
tuple_size<GTEST_$(n)_TUPLE_(U) >::value>::Eq(t, u);
}
template <GTEST_$(n)_TYPENAMES_(T), GTEST_$(n)_TYPENAMES_(U)>
inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t,
const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); }
// 6.1.4 Pairs.
// Unimplemented.
} // namespace tr1
} // namespace std
$for j [[
#undef GTEST_$(j)_TUPLE_
]]
$for j [[
#undef GTEST_$(j)_TYPENAMES_
]]
#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
#undef GTEST_BY_REF_
#undef GTEST_ADD_REF_
#undef GTEST_TUPLE_ELEMENT_
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_

File diff suppressed because it is too large Load diff

View file

@ -1,297 +0,0 @@
$$ -*- mode: c++; -*-
$var n = 50 $$ Maximum length of type lists we want to support.
// Copyright 2008 Google Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Type utilities needed for implementing typed and type-parameterized
// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
//
// Currently we support at most $n types in a list, and at most $n
// type-parameterized tests in one type-parameterized test case.
// Please contact googletestframework@googlegroups.com if you need
// more.
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
#include "gtest/internal/gtest-port.h"
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
// libstdc++ (which is where cxxabi.h comes from).
# if GTEST_HAS_CXXABI_H_
# include <cxxabi.h>
# elif defined(__HP_aCC)
# include <acxx_demangle.h>
# endif // GTEST_HASH_CXXABI_H_
namespace testing {
namespace internal {
// GetTypeName<T>() returns a human-readable name of type T.
// NB: This function is also used in Google Mock, so don't move it inside of
// the typed-test-only section below.
template <typename T>
std::string GetTypeName() {
# if GTEST_HAS_RTTI
const char* const name = typeid(T).name();
# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
int status = 0;
// gcc's implementation of typeid(T).name() mangles the type name,
// so we have to demangle it.
# if GTEST_HAS_CXXABI_H_
using abi::__cxa_demangle;
# endif // GTEST_HAS_CXXABI_H_
char* const readable_name = __cxa_demangle(name, 0, 0, &status);
const std::string name_str(status == 0 ? readable_name : name);
free(readable_name);
return name_str;
# else
return name;
# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
# else
return "<type>";
# endif // GTEST_HAS_RTTI
}
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
// type. This can be used as a compile-time assertion to ensure that
// two types are equal.
template <typename T1, typename T2>
struct AssertTypeEq;
template <typename T>
struct AssertTypeEq<T, T> {
typedef bool type;
};
// A unique type used as the default value for the arguments of class
// template Types. This allows us to simulate variadic templates
// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
// support directly.
struct None {};
// The following family of struct and struct templates are used to
// represent type lists. In particular, TypesN<T1, T2, ..., TN>
// represents a type list with N types (T1, T2, ..., and TN) in it.
// Except for Types0, every struct in the family has two member types:
// Head for the first type in the list, and Tail for the rest of the
// list.
// The empty type list.
struct Types0 {};
// Type lists of length 1, 2, 3, and so on.
template <typename T1>
struct Types1 {
typedef T1 Head;
typedef Types0 Tail;
};
$range i 2..n
$for i [[
$range j 1..i
$range k 2..i
template <$for j, [[typename T$j]]>
struct Types$i {
typedef T1 Head;
typedef Types$(i-1)<$for k, [[T$k]]> Tail;
};
]]
} // namespace internal
// We don't want to require the users to write TypesN<...> directly,
// as that would require them to count the length. Types<...> is much
// easier to write, but generates horrible messages when there is a
// compiler error, as gcc insists on printing out each template
// argument, even if it has the default value (this means Types<int>
// will appear as Types<int, None, None, ..., None> in the compiler
// errors).
//
// Our solution is to combine the best part of the two approaches: a
// user would write Types<T1, ..., TN>, and Google Test will translate
// that to TypesN<T1, ..., TN> internally to make error messages
// readable. The translation is done by the 'type' member of the
// Types template.
$range i 1..n
template <$for i, [[typename T$i = internal::None]]>
struct Types {
typedef internal::Types$n<$for i, [[T$i]]> type;
};
template <>
struct Types<$for i, [[internal::None]]> {
typedef internal::Types0 type;
};
$range i 1..n-1
$for i [[
$range j 1..i
$range k i+1..n
template <$for j, [[typename T$j]]>
struct Types<$for j, [[T$j]]$for k[[, internal::None]]> {
typedef internal::Types$i<$for j, [[T$j]]> type;
};
]]
namespace internal {
# define GTEST_TEMPLATE_ template <typename T> class
// The template "selector" struct TemplateSel<Tmpl> is used to
// represent Tmpl, which must be a class template with one type
// parameter, as a type. TemplateSel<Tmpl>::Bind<T>::type is defined
// as the type Tmpl<T>. This allows us to actually instantiate the
// template "selected" by TemplateSel<Tmpl>.
//
// This trick is necessary for simulating typedef for class templates,
// which C++ doesn't support directly.
template <GTEST_TEMPLATE_ Tmpl>
struct TemplateSel {
template <typename T>
struct Bind {
typedef Tmpl<T> type;
};
};
# define GTEST_BIND_(TmplSel, T) \
TmplSel::template Bind<T>::type
// A unique struct template used as the default value for the
// arguments of class template Templates. This allows us to simulate
// variadic templates (e.g. Templates<int>, Templates<int, double>,
// and etc), which C++ doesn't support directly.
template <typename T>
struct NoneT {};
// The following family of struct and struct templates are used to
// represent template lists. In particular, TemplatesN<T1, T2, ...,
// TN> represents a list of N templates (T1, T2, ..., and TN). Except
// for Templates0, every struct in the family has two member types:
// Head for the selector of the first template in the list, and Tail
// for the rest of the list.
// The empty template list.
struct Templates0 {};
// Template lists of length 1, 2, 3, and so on.
template <GTEST_TEMPLATE_ T1>
struct Templates1 {
typedef TemplateSel<T1> Head;
typedef Templates0 Tail;
};
$range i 2..n
$for i [[
$range j 1..i
$range k 2..i
template <$for j, [[GTEST_TEMPLATE_ T$j]]>
struct Templates$i {
typedef TemplateSel<T1> Head;
typedef Templates$(i-1)<$for k, [[T$k]]> Tail;
};
]]
// We don't want to require the users to write TemplatesN<...> directly,
// as that would require them to count the length. Templates<...> is much
// easier to write, but generates horrible messages when there is a
// compiler error, as gcc insists on printing out each template
// argument, even if it has the default value (this means Templates<list>
// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
// errors).
//
// Our solution is to combine the best part of the two approaches: a
// user would write Templates<T1, ..., TN>, and Google Test will translate
// that to TemplatesN<T1, ..., TN> internally to make error messages
// readable. The translation is done by the 'type' member of the
// Templates template.
$range i 1..n
template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]>
struct Templates {
typedef Templates$n<$for i, [[T$i]]> type;
};
template <>
struct Templates<$for i, [[NoneT]]> {
typedef Templates0 type;
};
$range i 1..n-1
$for i [[
$range j 1..i
$range k i+1..n
template <$for j, [[GTEST_TEMPLATE_ T$j]]>
struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> {
typedef Templates$i<$for j, [[T$j]]> type;
};
]]
// The TypeList template makes it possible to use either a single type
// or a Types<...> list in TYPED_TEST_CASE() and
// INSTANTIATE_TYPED_TEST_CASE_P().
template <typename T>
struct TypeList {
typedef Types1<T> type;
};
$range i 1..n
template <$for i, [[typename T$i]]>
struct TypeList<Types<$for i, [[T$i]]> > {
typedef typename Types<$for i, [[T$i]]>::type type;
};
#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
} // namespace internal
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_

Some files were not shown because too many files have changed in this diff Show more