initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled

This commit is contained in:
2025-09-16 20:46:46 -04:00
commit 9d30169a8d
13378 changed files with 7050105 additions and 0 deletions

280
thirdparty/cvtt/ConvectionKernels.h vendored Normal file
View File

@@ -0,0 +1,280 @@
/*
Convection Texture Tools
Copyright (c) 2018 Eric Lasota
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.
*/
#pragma once
#ifndef __CVTT_CONVECTION_KERNELS__
#define __CVTT_CONVECTION_KERNELS__
#include <stddef.h>
#include <stdint.h>
namespace cvtt
{
namespace Flags
{
// Use fast indexing in BC7 encoding (about 2x faster, slightly worse quality)
const uint32_t BC7_FastIndexing = 0x008;
// Try precomputed single-color lookups where applicable (slightly slower, small quality increase on specific blocks)
const uint32_t BC7_TrySingleColor = 0x010;
// Don't allow non-zero or non-max alpha values in blocks that only contain one or the other
const uint32_t BC7_RespectPunchThrough = 0x020;
// Use fast indexing in HDR formats (faster, worse quality)
const uint32_t BC6H_FastIndexing = 0x040;
// Exhaustive search RGB orderings when encoding BC1-BC3 (much slower, better quality)
const uint32_t S3TC_Exhaustive = 0x080;
// Penalize distant endpoints, improving quality on inaccurate GPU decoders
const uint32_t S3TC_Paranoid = 0x100;
// Uniform color channel importance
const uint32_t Uniform = 0x200;
// Use fake BT.709 color space for etc2comp compatibility (slower)
const uint32_t ETC_UseFakeBT709 = 0x400;
// Use accurate quantization functions when quantizing fake BT.709 (much slower, marginal improvement on specific blocks)
const uint32_t ETC_FakeBT709Accurate = 0x800;
// Misc useful default flag combinations
const uint32_t Fastest = (BC6H_FastIndexing | BC7_FastIndexing | S3TC_Paranoid);
const uint32_t Faster = (BC6H_FastIndexing | BC7_FastIndexing | S3TC_Paranoid);
const uint32_t Fast = (BC7_FastIndexing | S3TC_Paranoid);
const uint32_t Default = (BC7_FastIndexing | S3TC_Paranoid);
const uint32_t Better = (S3TC_Paranoid | S3TC_Exhaustive);
const uint32_t Ultra = (BC7_TrySingleColor | S3TC_Paranoid | S3TC_Exhaustive | ETC_FakeBT709Accurate);
}
const unsigned int NumParallelBlocks = 8;
struct Options
{
uint32_t flags; // Bitmask of cvtt::Flags values
float threshold; // Alpha test threshold for BC1
float redWeight; // Red channel importance
float greenWeight; // Green channel importance
float blueWeight; // Blue channel importance
float alphaWeight; // Alpha channel importance
int refineRoundsBC7; // Number of refine rounds for BC7
int refineRoundsBC6H; // Number of refine rounds for BC6H (max 3)
int refineRoundsIIC; // Number of refine rounds for independent interpolated channels (BC3 alpha, BC4, BC5)
int refineRoundsS3TC; // Number of refine rounds for S3TC RGB
int seedPoints; // Number of seed points (min 1, max 4)
Options()
: flags(Flags::Default)
, threshold(0.5f)
, redWeight(0.2125f / 0.7154f)
, greenWeight(1.0f)
, blueWeight(0.0721f / 0.7154f)
, alphaWeight(1.0f)
, refineRoundsBC7(2)
, refineRoundsBC6H(3)
, refineRoundsIIC(8)
, refineRoundsS3TC(2)
, seedPoints(4)
{
}
};
struct BC7FineTuningParams
{
// Seed point counts for each mode+configuration combination
uint8_t mode0SP[16];
uint8_t mode1SP[64];
uint8_t mode2SP[64];
uint8_t mode3SP[64];
uint8_t mode4SP[4][2];
uint8_t mode5SP[4];
uint8_t mode6SP;
uint8_t mode7SP[64];
BC7FineTuningParams()
{
for (int i = 0; i < 16; i++)
this->mode0SP[i] = 4;
for (int i = 0; i < 64; i++)
{
this->mode1SP[i] = 4;
this->mode2SP[i] = 4;
this->mode3SP[i] = 4;
this->mode7SP[i] = 4;
}
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 2; j++)
this->mode4SP[i][j] = 4;
this->mode5SP[i] = 4;
}
this->mode6SP = 4;
}
};
struct BC7EncodingPlan
{
static const int kNumRGBAShapes = 129;
static const int kNumRGBShapes = 243;
uint64_t mode1PartitionEnabled;
uint64_t mode2PartitionEnabled;
uint64_t mode3PartitionEnabled;
uint16_t mode0PartitionEnabled;
uint64_t mode7RGBAPartitionEnabled;
uint64_t mode7RGBPartitionEnabled;
uint8_t mode4SP[4][2];
uint8_t mode5SP[4];
bool mode6Enabled;
uint8_t seedPointsForShapeRGB[kNumRGBShapes];
uint8_t seedPointsForShapeRGBA[kNumRGBAShapes];
uint8_t rgbaShapeList[kNumRGBAShapes];
uint8_t rgbaNumShapesToEvaluate;
uint8_t rgbShapeList[kNumRGBShapes];
uint8_t rgbNumShapesToEvaluate;
BC7EncodingPlan()
{
for (int i = 0; i < kNumRGBShapes; i++)
{
this->rgbShapeList[i] = i;
this->seedPointsForShapeRGB[i] = 4;
}
this->rgbNumShapesToEvaluate = kNumRGBShapes;
for (int i = 0; i < kNumRGBAShapes; i++)
{
this->rgbaShapeList[i] = i;
this->seedPointsForShapeRGBA[i] = 4;
}
this->rgbaNumShapesToEvaluate = kNumRGBAShapes;
this->mode0PartitionEnabled = 0xffff;
this->mode1PartitionEnabled = 0xffffffffffffffffULL;
this->mode2PartitionEnabled = 0xffffffffffffffffULL;
this->mode3PartitionEnabled = 0xffffffffffffffffULL;
this->mode6Enabled = true;
this->mode7RGBPartitionEnabled = 0xffffffffffffffffULL;
this->mode7RGBAPartitionEnabled = 0xffffffffffffffffULL;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 2; j++)
this->mode4SP[i][j] = 4;
this->mode5SP[i] = 4;
}
}
};
// RGBA input block for unsigned 8-bit formats
struct PixelBlockU8
{
uint8_t m_pixels[16][4];
};
// RGBA input block for signed 8-bit formats
struct PixelBlockS8
{
int8_t m_pixels[16][4];
};
struct PixelBlockScalarS16
{
int16_t m_pixels[16];
};
// RGBA input block for half-precision float formats (bit-cast to int16_t)
struct PixelBlockF16
{
int16_t m_pixels[16][4];
};
class ETC2CompressionData
{
protected:
ETC2CompressionData() {}
};
class ETC1CompressionData
{
protected:
ETC1CompressionData() {}
};
namespace Kernels
{
typedef void* allocFunc_t(void *context, size_t size);
typedef void freeFunc_t(void *context, void* ptr, size_t size);
// NOTE: All functions accept and output NumParallelBlocks blocks at once
void EncodeBC1(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options);
void EncodeBC2(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options);
void EncodeBC3(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options);
void EncodeBC4U(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options);
void EncodeBC4S(uint8_t *pBC, const PixelBlockS8 *pBlocks, const Options &options);
void EncodeBC5U(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options);
void EncodeBC5S(uint8_t *pBC, const PixelBlockS8 *pBlocks, const Options &options);
void EncodeBC6HU(uint8_t *pBC, const PixelBlockF16 *pBlocks, const Options &options);
void EncodeBC6HS(uint8_t *pBC, const PixelBlockF16 *pBlocks, const Options &options);
void EncodeBC7(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options, const BC7EncodingPlan &encodingPlan);
void EncodeETC1(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options, ETC1CompressionData *compressionData);
void EncodeETC2(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options, ETC2CompressionData *compressionData);
void EncodeETC2RGBA(uint8_t *pBC, const PixelBlockU8 *pBlocks, const cvtt::Options &options, cvtt::ETC2CompressionData *compressionData);
void EncodeETC2PunchthroughAlpha(uint8_t *pBC, const PixelBlockU8 *pBlocks, const cvtt::Options &options, cvtt::ETC2CompressionData *compressionData);
void EncodeETC2Alpha(uint8_t *pBC, const PixelBlockU8 *pBlocks, const cvtt::Options &options);
void EncodeETC2Alpha11(uint8_t *pBC, const PixelBlockScalarS16 *pBlocks, bool isSigned, const cvtt::Options &options);
// Generates a BC7 encoding plan from a quality parameter that ranges from 1 (fastest) to 100 (best)
void ConfigureBC7EncodingPlanFromQuality(BC7EncodingPlan &encodingPlan, int quality);
// Generates a BC7 encoding plan from fine-tuning parameters.
bool ConfigureBC7EncodingPlanFromFineTuningParams(BC7EncodingPlan &encodingPlan, const BC7FineTuningParams &params);
// ETC compression requires temporary storage that normally consumes a large amount of stack space.
// To allocate and release it, use one of these functions.
ETC2CompressionData *AllocETC2Data(allocFunc_t allocFunc, void *context, const cvtt::Options &options);
void ReleaseETC2Data(ETC2CompressionData *compressionData, freeFunc_t freeFunc);
ETC1CompressionData *AllocETC1Data(allocFunc_t allocFunc, void *context);
void ReleaseETC1Data(ETC1CompressionData *compressionData, freeFunc_t freeFunc);
void DecodeBC6HU(PixelBlockF16 *pBlocks, const uint8_t *pBC);
void DecodeBC6HS(PixelBlockF16 *pBlocks, const uint8_t *pBC);
void DecodeBC7(PixelBlockU8 *pBlocks, const uint8_t *pBC);
}
}
#endif

View File

@@ -0,0 +1,346 @@
/*
Convection Texture Tools
Copyright (c) 2018-2019 Eric Lasota
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.
*/
#include "ConvectionKernels_Config.h"
#if !defined(CVTT_SINGLE_FILE) || defined(CVTT_SINGLE_FILE_IMPL)
#include <stdint.h>
#include "ConvectionKernels.h"
#include "ConvectionKernels_Util.h"
#include "ConvectionKernels_BC67.h"
#include "ConvectionKernels_ETC.h"
#include "ConvectionKernels_S3TC.h"
#include <assert.h>
namespace cvtt
{
namespace Kernels
{
void EncodeBC7(uint8_t *pBC, const PixelBlockU8 *pBlocks, const cvtt::Options &options, const BC7EncodingPlan &encodingPlan)
{
assert(pBlocks);
assert(pBC);
float channelWeights[4];
Util::FillWeights(options, channelWeights);
for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
Internal::BC7Computer::Pack(options.flags, pBlocks + blockBase, pBC, channelWeights, encodingPlan, options.refineRoundsBC7);
pBC += ParallelMath::ParallelSize * 16;
}
}
void EncodeBC6HU(uint8_t *pBC, const PixelBlockF16 *pBlocks, const cvtt::Options &options)
{
assert(pBlocks);
assert(pBC);
float channelWeights[4];
Util::FillWeights(options, channelWeights);
for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
Internal::BC6HComputer::Pack(options.flags, pBlocks + blockBase, pBC, channelWeights, false, options.seedPoints, options.refineRoundsBC6H);
pBC += ParallelMath::ParallelSize * 16;
}
}
void EncodeBC6HS(uint8_t *pBC, const PixelBlockF16 *pBlocks, const cvtt::Options &options)
{
assert(pBlocks);
assert(pBC);
float channelWeights[4];
Util::FillWeights(options, channelWeights);
for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
Internal::BC6HComputer::Pack(options.flags, pBlocks + blockBase, pBC, channelWeights, true, options.seedPoints, options.refineRoundsBC6H);
pBC += ParallelMath::ParallelSize * 16;
}
}
void EncodeBC1(uint8_t *pBC, const PixelBlockU8 *pBlocks, const cvtt::Options &options)
{
assert(pBlocks);
assert(pBC);
float channelWeights[4];
Util::FillWeights(options, channelWeights);
for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
Internal::S3TCComputer::PackRGB(options.flags, pBlocks + blockBase, pBC, 8, channelWeights, true, options.threshold, (options.flags & Flags::S3TC_Exhaustive) != 0, options.seedPoints, options.refineRoundsS3TC);
pBC += ParallelMath::ParallelSize * 8;
}
}
void EncodeBC2(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options)
{
assert(pBlocks);
assert(pBC);
float channelWeights[4];
Util::FillWeights(options, channelWeights);
for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
Internal::S3TCComputer::PackRGB(options.flags, pBlocks + blockBase, pBC + 8, 16, channelWeights, false, 1.0f, (options.flags & Flags::S3TC_Exhaustive) != 0, options.seedPoints, options.refineRoundsS3TC);
Internal::S3TCComputer::PackExplicitAlpha(options.flags, pBlocks + blockBase, 3, pBC, 16);
pBC += ParallelMath::ParallelSize * 16;
}
}
void EncodeBC3(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options)
{
assert(pBlocks);
assert(pBC);
float channelWeights[4];
Util::FillWeights(options, channelWeights);
for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
Internal::S3TCComputer::PackRGB(options.flags, pBlocks + blockBase, pBC + 8, 16, channelWeights, false, 1.0f, (options.flags & Flags::S3TC_Exhaustive) != 0, options.seedPoints, options.refineRoundsS3TC);
Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, pBlocks + blockBase, 3, pBC, 16, false, options.seedPoints, options.refineRoundsIIC);
pBC += ParallelMath::ParallelSize * 16;
}
}
void EncodeBC4U(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options)
{
assert(pBlocks);
assert(pBC);
float channelWeights[4];
Util::FillWeights(options, channelWeights);
for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, pBlocks + blockBase, 0, pBC, 8, false, options.seedPoints, options.refineRoundsIIC);
pBC += ParallelMath::ParallelSize * 8;
}
}
void EncodeBC4S(uint8_t *pBC, const PixelBlockS8 *pBlocks, const Options &options)
{
assert(pBlocks);
assert(pBC);
float channelWeights[4];
Util::FillWeights(options, channelWeights);
for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
PixelBlockU8 inputBlocks[ParallelMath::ParallelSize];
Util::BiasSignedInput(inputBlocks, pBlocks + blockBase);
Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, inputBlocks, 0, pBC, 8, true, options.seedPoints, options.refineRoundsIIC);
pBC += ParallelMath::ParallelSize * 8;
}
}
void EncodeBC5U(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options)
{
assert(pBlocks);
assert(pBC);
float channelWeights[4];
Util::FillWeights(options, channelWeights);
for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, pBlocks + blockBase, 0, pBC, 16, false, options.seedPoints, options.refineRoundsIIC);
Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, pBlocks + blockBase, 1, pBC + 8, 16, false, options.seedPoints, options.refineRoundsIIC);
pBC += ParallelMath::ParallelSize * 16;
}
}
void EncodeBC5S(uint8_t *pBC, const PixelBlockS8 *pBlocks, const Options &options)
{
assert(pBlocks);
assert(pBC);
float channelWeights[4];
Util::FillWeights(options, channelWeights);
for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
PixelBlockU8 inputBlocks[ParallelMath::ParallelSize];
Util::BiasSignedInput(inputBlocks, pBlocks + blockBase);
Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, inputBlocks, 0, pBC, 16, true, options.seedPoints, options.refineRoundsIIC);
Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, inputBlocks, 1, pBC + 8, 16, true, options.seedPoints, options.refineRoundsIIC);
pBC += ParallelMath::ParallelSize * 16;
}
}
void EncodeETC1(uint8_t *pBC, const PixelBlockU8 *pBlocks, const cvtt::Options &options, cvtt::ETC1CompressionData *compressionData)
{
assert(pBlocks);
assert(pBC);
float channelWeights[4];
Util::FillWeights(options, channelWeights);
for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
Internal::ETCComputer::CompressETC1Block(pBC, pBlocks + blockBase, compressionData, options);
pBC += ParallelMath::ParallelSize * 8;
}
}
void EncodeETC2(uint8_t *pBC, const PixelBlockU8 *pBlocks, const cvtt::Options &options, cvtt::ETC2CompressionData *compressionData)
{
assert(pBlocks);
assert(pBC);
float channelWeights[4];
Util::FillWeights(options, channelWeights);
for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
Internal::ETCComputer::CompressETC2Block(pBC, pBlocks + blockBase, compressionData, options, false);
pBC += ParallelMath::ParallelSize * 8;
}
}
void EncodeETC2PunchthroughAlpha(uint8_t *pBC, const PixelBlockU8 *pBlocks, const cvtt::Options &options, cvtt::ETC2CompressionData *compressionData)
{
assert(pBlocks);
assert(pBC);
float channelWeights[4];
Util::FillWeights(options, channelWeights);
for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
Internal::ETCComputer::CompressETC2Block(pBC, pBlocks + blockBase, compressionData, options, true);
pBC += ParallelMath::ParallelSize * 8;
}
}
void EncodeETC2Alpha(uint8_t *pBC, const PixelBlockU8 *pBlocks, const cvtt::Options &options)
{
assert(pBlocks);
assert(pBC);
for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
Internal::ETCComputer::CompressETC2AlphaBlock(pBC, pBlocks + blockBase, options);
pBC += ParallelMath::ParallelSize * 8;
}
}
void EncodeETC2Alpha11(uint8_t *pBC, const PixelBlockScalarS16 *pBlocks, bool isSigned, const cvtt::Options &options)
{
assert(pBlocks);
assert(pBC);
for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize)
{
Internal::ETCComputer::CompressEACBlock(pBC, pBlocks + blockBase, isSigned, options);
pBC += ParallelMath::ParallelSize * 8;
}
}
void EncodeETC2RGBA(uint8_t *pBC, const PixelBlockU8 *pBlocks, const cvtt::Options &options, cvtt::ETC2CompressionData *compressionData)
{
uint8_t alphaBlockData[cvtt::NumParallelBlocks * 8];
uint8_t colorBlockData[cvtt::NumParallelBlocks * 8];
EncodeETC2(colorBlockData, pBlocks, options, compressionData);
EncodeETC2Alpha(alphaBlockData, pBlocks, options);
for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase++)
{
for (size_t blockData = 0; blockData < 8; blockData++)
pBC[blockBase * 16 + blockData] = alphaBlockData[blockBase * 8 + blockData];
for (size_t blockData = 0; blockData < 8; blockData++)
pBC[blockBase * 16 + 8 + blockData] = colorBlockData[blockBase * 8 + blockData];
}
}
void DecodeBC7(PixelBlockU8 *pBlocks, const uint8_t *pBC)
{
assert(pBlocks);
assert(pBC);
for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase++)
{
Internal::BC7Computer::UnpackOne(pBlocks[blockBase], pBC);
pBC += 16;
}
}
void DecodeBC6HU(PixelBlockF16 *pBlocks, const uint8_t *pBC)
{
assert(pBlocks);
assert(pBC);
for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase++)
{
Internal::BC6HComputer::UnpackOne(pBlocks[blockBase], pBC, false);
pBC += 16;
}
}
void DecodeBC6HS(PixelBlockF16 *pBlocks, const uint8_t *pBC)
{
assert(pBlocks);
assert(pBC);
for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase++)
{
Internal::BC6HComputer::UnpackOne(pBlocks[blockBase], pBC, true);
pBC += 16;
}
}
ETC1CompressionData *AllocETC1Data(allocFunc_t allocFunc, void *context)
{
return cvtt::Internal::ETCComputer::AllocETC1Data(allocFunc, context);
}
void ReleaseETC1Data(ETC1CompressionData *compressionData, freeFunc_t freeFunc)
{
cvtt::Internal::ETCComputer::ReleaseETC1Data(compressionData, freeFunc);
}
ETC2CompressionData *AllocETC2Data(allocFunc_t allocFunc, void *context, const cvtt::Options &options)
{
return cvtt::Internal::ETCComputer::AllocETC2Data(allocFunc, context, options);
}
void ReleaseETC2Data(ETC2CompressionData *compressionData, freeFunc_t freeFunc)
{
cvtt::Internal::ETCComputer::ReleaseETC2Data(compressionData, freeFunc);
}
}
}
#endif

View File

@@ -0,0 +1,55 @@
#pragma once
#ifndef __CVTT_AGGREGATEDERROR_H__
#define __CVTT_AGGREGATEDERROR_H__
#include "ConvectionKernels_ParallelMath.h"
namespace cvtt
{
namespace Internal
{
template<int TVectorSize>
class AggregatedError
{
public:
typedef ParallelMath::UInt16 MUInt16;
typedef ParallelMath::UInt31 MUInt31;
typedef ParallelMath::Float MFloat;
AggregatedError()
{
for (int ch = 0; ch < TVectorSize; ch++)
m_errorUnweighted[ch] = ParallelMath::MakeUInt31(0);
}
void Add(const MUInt16 &channelErrorUnweighted, int ch)
{
m_errorUnweighted[ch] = m_errorUnweighted[ch] + ParallelMath::ToUInt31(channelErrorUnweighted);
}
MFloat Finalize(uint32_t flags, const float channelWeightsSq[TVectorSize]) const
{
if (flags & cvtt::Flags::Uniform)
{
MUInt31 total = m_errorUnweighted[0];
for (int ch = 1; ch < TVectorSize; ch++)
total = total + m_errorUnweighted[ch];
return ParallelMath::ToFloat(total);
}
else
{
MFloat total = ParallelMath::ToFloat(m_errorUnweighted[0]) * channelWeightsSq[0];
for (int ch = 1; ch < TVectorSize; ch++)
total = total + ParallelMath::ToFloat(m_errorUnweighted[ch]) * channelWeightsSq[ch];
return total;
}
}
private:
MUInt31 m_errorUnweighted[TVectorSize];
};
}
}
#endif

3760
thirdparty/cvtt/ConvectionKernels_BC67.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,99 @@
#pragma once
#include "ConvectionKernels_ParallelMath.h"
namespace cvtt
{
namespace Tables
{
namespace BC7SC
{
struct Table;
}
}
namespace Internal
{
namespace BC67
{
struct WorkInfo;
}
template<int TVectorSize>
class IndexSelectorHDR;
}
struct PixelBlockU8;
}
namespace cvtt
{
namespace Internal
{
class BC7Computer
{
public:
static void Pack(uint32_t flags, const PixelBlockU8* inputs, uint8_t* packedBlocks, const float channelWeights[4], const BC7EncodingPlan &encodingPlan, int numRefineRounds);
static void UnpackOne(PixelBlockU8 &output, const uint8_t* packedBlock);
private:
static const int MaxTweakRounds = 4;
typedef ParallelMath::SInt16 MSInt16;
typedef ParallelMath::UInt15 MUInt15;
typedef ParallelMath::UInt16 MUInt16;
typedef ParallelMath::SInt32 MSInt32;
typedef ParallelMath::Float MFloat;
static void TweakAlpha(const MUInt15 original[2], int tweak, int range, MUInt15 result[2]);
static void Quantize(MUInt15* color, int bits, int channels);
static void QuantizeP(MUInt15* color, int bits, uint16_t p, int channels);
static void Unquantize(MUInt15* color, int bits, int channels);
static void CompressEndpoints0(MUInt15 ep[2][4], uint16_t p[2]);
static void CompressEndpoints1(MUInt15 ep[2][4], uint16_t p);
static void CompressEndpoints2(MUInt15 ep[2][4]);
static void CompressEndpoints3(MUInt15 ep[2][4], uint16_t p[2]);
static void CompressEndpoints4(MUInt15 epRGB[2][3], MUInt15 epA[2]);
static void CompressEndpoints5(MUInt15 epRGB[2][3], MUInt15 epA[2]);
static void CompressEndpoints6(MUInt15 ep[2][4], uint16_t p[2]);
static void CompressEndpoints7(MUInt15 ep[2][4], uint16_t p[2]);
static void TrySingleColorRGBAMultiTable(uint32_t flags, const MUInt15 pixels[16][4], const MFloat average[4], int numRealChannels, const uint8_t *fragmentStart, int shapeLength, const MFloat &staticAlphaError, const ParallelMath::Int16CompFlag punchThroughInvalid[4], MFloat& shapeBestError, MUInt15 shapeBestEP[2][4], MUInt15 *fragmentBestIndexes, const float *channelWeightsSq, const cvtt::Tables::BC7SC::Table*const* tables, int numTables, const ParallelMath::RoundTowardNearestForScope *rtn);
static void TrySinglePlane(uint32_t flags, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], const float channelWeights[4], const BC7EncodingPlan &encodingPlan, int numRefineRounds, BC67::WorkInfo& work, const ParallelMath::RoundTowardNearestForScope *rtn);
static void TryDualPlane(uint32_t flags, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], const float channelWeights[4], const BC7EncodingPlan &encodingPlan, int numRefineRounds, BC67::WorkInfo& work, const ParallelMath::RoundTowardNearestForScope *rtn);
template<class T>
static void Swap(T& a, T& b);
};
class BC6HComputer
{
public:
static void Pack(uint32_t flags, const PixelBlockF16* inputs, uint8_t* packedBlocks, const float channelWeights[4], bool isSigned, int numTweakRounds, int numRefineRounds);
static void UnpackOne(PixelBlockF16 &output, const uint8_t *pBC, bool isSigned);
private:
typedef ParallelMath::Float MFloat;
typedef ParallelMath::SInt16 MSInt16;
typedef ParallelMath::UInt16 MUInt16;
typedef ParallelMath::UInt15 MUInt15;
typedef ParallelMath::AInt16 MAInt16;
typedef ParallelMath::SInt32 MSInt32;
typedef ParallelMath::UInt31 MUInt31;
static const int MaxTweakRounds = 4;
static const int MaxRefineRounds = 3;
static MSInt16 QuantizeSingleEndpointElementSigned(const MSInt16 &elem2CL, int precision, const ParallelMath::RoundUpForScope* ru);
static MUInt15 QuantizeSingleEndpointElementUnsigned(const MUInt15 &elem, int precision, const ParallelMath::RoundUpForScope* ru);
static void UnquantizeSingleEndpointElementSigned(const MSInt16 &comp, int precision, MSInt16 &outUnquantized, MSInt16 &outUnquantizedFinished2CL);
static void UnquantizeSingleEndpointElementUnsigned(const MUInt15 &comp, int precision, MUInt16 &outUnquantized, MUInt16 &outUnquantizedFinished);
static void QuantizeEndpointsSigned(const MSInt16 endPoints[2][3], const MFloat floatPixelsColorSpace[16][3], const MFloat floatPixelsLinearWeighted[16][3], MAInt16 quantizedEndPoints[2][3], MUInt15 indexes[16], IndexSelectorHDR<3> &indexSelector, int fixupIndex, int precision, int indexRange, const float *channelWeights, bool fastIndexing, const ParallelMath::RoundTowardNearestForScope *rtn);
static void QuantizeEndpointsUnsigned(const MSInt16 endPoints[2][3], const MFloat floatPixelsColorSpace[16][3], const MFloat floatPixelsLinearWeighted[16][3], MAInt16 quantizedEndPoints[2][3], MUInt15 indexes[16], IndexSelectorHDR<3> &indexSelector, int fixupIndex, int precision, int indexRange, const float *channelWeights, bool fastIndexing, const ParallelMath::RoundTowardNearestForScope *rtn);
static void EvaluatePartitionedLegality(const MAInt16 ep0[2][3], const MAInt16 ep1[2][3], int aPrec, const int bPrec[3], bool isTransformed, MAInt16 outEncodedEPs[2][2][3], ParallelMath::Int16CompFlag& outIsLegal);
static void EvaluateSingleLegality(const MAInt16 ep[2][3], int aPrec, const int bPrec[3], bool isTransformed, MAInt16 outEncodedEPs[2][3], ParallelMath::Int16CompFlag& outIsLegal);
static void SignExtendSingle(int &v, int bits);
};
}
}

View File

@@ -0,0 +1,881 @@
/*
Convection Texture Tools
Copyright (c) 2018-2019 Eric Lasota
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.
-------------------------------------------------------------------------------------
Portions based on DirectX Texture Library (DirectXTex)
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
http://go.microsoft.com/fwlink/?LinkId=248926
*/
#include "ConvectionKernels_Config.h"
#if !defined(CVTT_SINGLE_FILE) || defined(CVTT_SINGLE_FILE_IMPL)
#include "ConvectionKernels_BC6H_IO.h"
namespace cvtt
{
namespace BC6H_IO
{
void WriteMode0(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz)
{
encoded[0] = (m & 0x3u) | ((gy >> 2) & 0x4u) | ((by >> 1) & 0x8u) | (bz & 0x10u) | ((rw << 5) & 0x7fe0u) | ((gw << 15) & 0x1ff8000u) | ((bw << 25) & 0xfe000000u);
encoded[1] = ((bw >> 7) & 0x7u) | ((rx << 3) & 0xf8u) | ((gz << 4) & 0x100u) | ((gy << 9) & 0x1e00u) | ((gx << 13) & 0x3e000u) | ((bz << 18) & 0x40000u) | ((gz << 19) & 0x780000u) | ((bx << 23) & 0xf800000u) | ((bz << 27) & 0x10000000u) | ((by << 29) & 0xe0000000u);
encoded[2] = ((by >> 3) & 0x1u) | ((ry << 1) & 0x3eu) | ((bz << 4) & 0x40u) | ((rz << 7) & 0xf80u) | ((bz << 9) & 0x1000u) | ((d << 13) & 0x3e000u);
}
void WriteMode1(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz)
{
encoded[0] = (m & 0x3u) | ((gy >> 3) & 0x4u) | ((gz >> 1) & 0x18u) | ((rw << 5) & 0xfe0u) | ((bz << 12) & 0x3000u) | ((by << 10) & 0x4000u) | ((gw << 15) & 0x3f8000u) | ((by << 17) & 0x400000u) | ((bz << 21) & 0x800000u) | ((gy << 20) & 0x1000000u) | ((bw << 25) & 0xfe000000u);
encoded[1] = ((bz >> 3) & 0x1u) | ((bz >> 4) & 0x2u) | ((bz >> 2) & 0x4u) | ((rx << 3) & 0x1f8u) | ((gy << 9) & 0x1e00u) | ((gx << 13) & 0x7e000u) | ((gz << 19) & 0x780000u) | ((bx << 23) & 0x1f800000u) | ((by << 29) & 0xe0000000u);
encoded[2] = ((by >> 3) & 0x1u) | ((ry << 1) & 0x7eu) | ((rz << 7) & 0x1f80u) | ((d << 13) & 0x3e000u);
}
void WriteMode2(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz)
{
encoded[0] = (m & 0x1fu) | ((rw << 5) & 0x7fe0u) | ((gw << 15) & 0x1ff8000u) | ((bw << 25) & 0xfe000000u);
encoded[1] = ((bw >> 7) & 0x7u) | ((rx << 3) & 0xf8u) | ((rw >> 2) & 0x100u) | ((gy << 9) & 0x1e00u) | ((gx << 13) & 0x1e000u) | ((gw << 7) & 0x20000u) | ((bz << 18) & 0x40000u) | ((gz << 19) & 0x780000u) | ((bx << 23) & 0x7800000u) | ((bw << 17) & 0x8000000u) | ((bz << 27) & 0x10000000u) | ((by << 29) & 0xe0000000u);
encoded[2] = ((by >> 3) & 0x1u) | ((ry << 1) & 0x3eu) | ((bz << 4) & 0x40u) | ((rz << 7) & 0xf80u) | ((bz << 9) & 0x1000u) | ((d << 13) & 0x3e000u);
}
void WriteMode3(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz)
{
encoded[0] = (m & 0x1fu) | ((rw << 5) & 0x7fe0u) | ((gw << 15) & 0x1ff8000u) | ((bw << 25) & 0xfe000000u);
encoded[1] = ((bw >> 7) & 0x7u) | ((rx << 3) & 0x78u) | ((rw >> 3) & 0x80u) | ((gz << 4) & 0x100u) | ((gy << 9) & 0x1e00u) | ((gx << 13) & 0x3e000u) | ((gw << 8) & 0x40000u) | ((gz << 19) & 0x780000u) | ((bx << 23) & 0x7800000u) | ((bw << 17) & 0x8000000u) | ((bz << 27) & 0x10000000u) | ((by << 29) & 0xe0000000u);
encoded[2] = ((by >> 3) & 0x1u) | ((ry << 1) & 0x1eu) | ((bz << 5) & 0x20u) | ((bz << 4) & 0x40u) | ((rz << 7) & 0x780u) | ((gy << 7) & 0x800u) | ((bz << 9) & 0x1000u) | ((d << 13) & 0x3e000u);
}
void WriteMode4(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz)
{
encoded[0] = (m & 0x1fu) | ((rw << 5) & 0x7fe0u) | ((gw << 15) & 0x1ff8000u) | ((bw << 25) & 0xfe000000u);
encoded[1] = ((bw >> 7) & 0x7u) | ((rx << 3) & 0x78u) | ((rw >> 3) & 0x80u) | ((by << 4) & 0x100u) | ((gy << 9) & 0x1e00u) | ((gx << 13) & 0x1e000u) | ((gw << 7) & 0x20000u) | ((bz << 18) & 0x40000u) | ((gz << 19) & 0x780000u) | ((bx << 23) & 0xf800000u) | ((bw << 18) & 0x10000000u) | ((by << 29) & 0xe0000000u);
encoded[2] = ((by >> 3) & 0x1u) | ((ry << 1) & 0x1eu) | ((bz << 4) & 0x60u) | ((rz << 7) & 0x780u) | ((bz << 7) & 0x800u) | ((bz << 9) & 0x1000u) | ((d << 13) & 0x3e000u);
}
void WriteMode5(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz)
{
encoded[0] = (m & 0x1fu) | ((rw << 5) & 0x3fe0u) | ((by << 10) & 0x4000u) | ((gw << 15) & 0xff8000u) | ((gy << 20) & 0x1000000u) | ((bw << 25) & 0xfe000000u);
encoded[1] = ((bw >> 7) & 0x3u) | ((bz >> 2) & 0x4u) | ((rx << 3) & 0xf8u) | ((gz << 4) & 0x100u) | ((gy << 9) & 0x1e00u) | ((gx << 13) & 0x3e000u) | ((bz << 18) & 0x40000u) | ((gz << 19) & 0x780000u) | ((bx << 23) & 0xf800000u) | ((bz << 27) & 0x10000000u) | ((by << 29) & 0xe0000000u);
encoded[2] = ((by >> 3) & 0x1u) | ((ry << 1) & 0x3eu) | ((bz << 4) & 0x40u) | ((rz << 7) & 0xf80u) | ((bz << 9) & 0x1000u) | ((d << 13) & 0x3e000u);
}
void WriteMode6(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz)
{
encoded[0] = (m & 0x1fu) | ((rw << 5) & 0x1fe0u) | ((gz << 9) & 0x2000u) | ((by << 10) & 0x4000u) | ((gw << 15) & 0x7f8000u) | ((bz << 21) & 0x800000u) | ((gy << 20) & 0x1000000u) | ((bw << 25) & 0xfe000000u);
encoded[1] = ((bw >> 7) & 0x1u) | ((bz >> 2) & 0x6u) | ((rx << 3) & 0x1f8u) | ((gy << 9) & 0x1e00u) | ((gx << 13) & 0x3e000u) | ((bz << 18) & 0x40000u) | ((gz << 19) & 0x780000u) | ((bx << 23) & 0xf800000u) | ((bz << 27) & 0x10000000u) | ((by << 29) & 0xe0000000u);
encoded[2] = ((by >> 3) & 0x1u) | ((ry << 1) & 0x7eu) | ((rz << 7) & 0x1f80u) | ((d << 13) & 0x3e000u);
}
void WriteMode7(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz)
{
encoded[0] = (m & 0x1fu) | ((rw << 5) & 0x1fe0u) | ((bz << 13) & 0x2000u) | ((by << 10) & 0x4000u) | ((gw << 15) & 0x7f8000u) | ((gy << 18) & 0x800000u) | ((gy << 20) & 0x1000000u) | ((bw << 25) & 0xfe000000u);
encoded[1] = ((bw >> 7) & 0x1u) | ((gz >> 4) & 0x2u) | ((bz >> 2) & 0x4u) | ((rx << 3) & 0xf8u) | ((gz << 4) & 0x100u) | ((gy << 9) & 0x1e00u) | ((gx << 13) & 0x7e000u) | ((gz << 19) & 0x780000u) | ((bx << 23) & 0xf800000u) | ((bz << 27) & 0x10000000u) | ((by << 29) & 0xe0000000u);
encoded[2] = ((by >> 3) & 0x1u) | ((ry << 1) & 0x3eu) | ((bz << 4) & 0x40u) | ((rz << 7) & 0xf80u) | ((bz << 9) & 0x1000u) | ((d << 13) & 0x3e000u);
}
void WriteMode8(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz)
{
encoded[0] = (m & 0x1fu) | ((rw << 5) & 0x1fe0u) | ((bz << 12) & 0x2000u) | ((by << 10) & 0x4000u) | ((gw << 15) & 0x7f8000u) | ((by << 18) & 0x800000u) | ((gy << 20) & 0x1000000u) | ((bw << 25) & 0xfe000000u);
encoded[1] = ((bw >> 7) & 0x1u) | ((bz >> 4) & 0x2u) | ((bz >> 2) & 0x4u) | ((rx << 3) & 0xf8u) | ((gz << 4) & 0x100u) | ((gy << 9) & 0x1e00u) | ((gx << 13) & 0x3e000u) | ((bz << 18) & 0x40000u) | ((gz << 19) & 0x780000u) | ((bx << 23) & 0x1f800000u) | ((by << 29) & 0xe0000000u);
encoded[2] = ((by >> 3) & 0x1u) | ((ry << 1) & 0x3eu) | ((bz << 4) & 0x40u) | ((rz << 7) & 0xf80u) | ((bz << 9) & 0x1000u) | ((d << 13) & 0x3e000u);
}
void WriteMode9(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz)
{
encoded[0] = (m & 0x1fu) | ((rw << 5) & 0x7e0u) | ((gz << 7) & 0x800u) | ((bz << 12) & 0x3000u) | ((by << 10) & 0x4000u) | ((gw << 15) & 0x1f8000u) | ((gy << 16) & 0x200000u) | ((by << 17) & 0x400000u) | ((bz << 21) & 0x800000u) | ((gy << 20) & 0x1000000u) | ((bw << 25) & 0x7e000000u) | ((gz << 26) & 0x80000000u);
encoded[1] = ((bz >> 3) & 0x1u) | ((bz >> 4) & 0x2u) | ((bz >> 2) & 0x4u) | ((rx << 3) & 0x1f8u) | ((gy << 9) & 0x1e00u) | ((gx << 13) & 0x7e000u) | ((gz << 19) & 0x780000u) | ((bx << 23) & 0x1f800000u) | ((by << 29) & 0xe0000000u);
encoded[2] = ((by >> 3) & 0x1u) | ((ry << 1) & 0x7eu) | ((rz << 7) & 0x1f80u) | ((d << 13) & 0x3e000u);
}
void WriteMode10(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz)
{
encoded[0] = (m & 0x1fu) | ((rw << 5) & 0x7fe0u) | ((gw << 15) & 0x1ff8000u) | ((bw << 25) & 0xfe000000u);
encoded[1] = ((bw >> 7) & 0x7u) | ((rx << 3) & 0x1ff8u) | ((gx << 13) & 0x7fe000u) | ((bx << 23) & 0xff800000u);
encoded[2] = ((bx >> 9) & 0x1u);
}
void WriteMode11(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz)
{
encoded[0] = (m & 0x1fu) | ((rw << 5) & 0x7fe0u) | ((gw << 15) & 0x1ff8000u) | ((bw << 25) & 0xfe000000u);
encoded[1] = ((bw >> 7) & 0x7u) | ((rx << 3) & 0xff8u) | ((rw << 2) & 0x1000u) | ((gx << 13) & 0x3fe000u) | ((gw << 12) & 0x400000u) | ((bx << 23) & 0xff800000u);
encoded[2] = ((bw >> 10) & 0x1u);
}
void WriteMode12(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz)
{
encoded[0] = (m & 0x1fu) | ((rw << 5) & 0x7fe0u) | ((gw << 15) & 0x1ff8000u) | ((bw << 25) & 0xfe000000u);
encoded[1] = ((bw >> 7) & 0x7u) | ((rx << 3) & 0x7f8u) | (rw & 0x800u) | ((rw << 2) & 0x1000u) | ((gx << 13) & 0x1fe000u) | ((gw << 10) & 0x200000u) | ((gw << 12) & 0x400000u) | ((bx << 23) & 0x7f800000u) | ((bw << 20) & 0x80000000u);
encoded[2] = ((bw >> 10) & 0x1u);
}
void WriteMode13(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz)
{
encoded[0] = (m & 0x1fu) | ((rw << 5) & 0x7fe0u) | ((gw << 15) & 0x1ff8000u) | ((bw << 25) & 0xfe000000u);
encoded[1] = ((bw >> 7) & 0x7u) | ((rx << 3) & 0x78u) | ((rw >> 8) & 0x80u) | ((rw >> 6) & 0x100u) | ((rw >> 4) & 0x200u) | ((rw >> 2) & 0x400u) | (rw & 0x800u) | ((rw << 2) & 0x1000u) | ((gx << 13) & 0x1e000u) | ((gw << 2) & 0x20000u) | ((gw << 4) & 0x40000u) | ((gw << 6) & 0x80000u) | ((gw << 8) & 0x100000u) | ((gw << 10) & 0x200000u) | ((gw << 12) & 0x400000u) | ((bx << 23) & 0x7800000u) | ((bw << 12) & 0x8000000u) | ((bw << 14) & 0x10000000u) | ((bw << 16) & 0x20000000u) | ((bw << 18) & 0x40000000u) | ((bw << 20) & 0x80000000u);
encoded[2] = ((bw >> 10) & 0x1u);
}
void ReadMode0(const uint32_t *encoded, uint16_t &outD, uint16_t &outRW, uint16_t &outRX, uint16_t &outRY, uint16_t &outRZ, uint16_t &outGW, uint16_t &outGX, uint16_t &outGY, uint16_t &outGZ, uint16_t &outBW, uint16_t &outBX, uint16_t &outBY, uint16_t &outBZ)
{
uint16_t d = 0;
uint16_t rw = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t rz = 0;
uint16_t gw = 0;
uint16_t gx = 0;
uint16_t gy = 0;
uint16_t gz = 0;
uint16_t bw = 0;
uint16_t bx = 0;
uint16_t by = 0;
uint16_t bz = 0;
gy |= ((encoded[0] << 2) & 0x10u);
by |= ((encoded[0] << 1) & 0x10u);
bz |= (encoded[0] & 0x10u);
rw |= ((encoded[0] >> 5) & 0x3ffu);
gw |= ((encoded[0] >> 15) & 0x3ffu);
bw |= ((encoded[0] >> 25) & 0x7fu);
bw |= ((encoded[1] << 7) & 0x380u);
rx |= ((encoded[1] >> 3) & 0x1fu);
gz |= ((encoded[1] >> 4) & 0x10u);
gy |= ((encoded[1] >> 9) & 0xfu);
gx |= ((encoded[1] >> 13) & 0x1fu);
bz |= ((encoded[1] >> 18) & 0x1u);
gz |= ((encoded[1] >> 19) & 0xfu);
bx |= ((encoded[1] >> 23) & 0x1fu);
bz |= ((encoded[1] >> 27) & 0x2u);
by |= ((encoded[1] >> 29) & 0x7u);
by |= ((encoded[2] << 3) & 0x8u);
ry |= ((encoded[2] >> 1) & 0x1fu);
bz |= ((encoded[2] >> 4) & 0x4u);
rz |= ((encoded[2] >> 7) & 0x1fu);
bz |= ((encoded[2] >> 9) & 0x8u);
d |= ((encoded[2] >> 13) & 0x1fu);
outD = d;
outRW = rw;
outRX = rx;
outRY = ry;
outRZ = rz;
outGW = gw;
outGX = gx;
outGY = gy;
outGZ = gz;
outBW = bw;
outBX = bx;
outBY = by;
outBZ = bz;
}
void ReadMode1(const uint32_t *encoded, uint16_t &outD, uint16_t &outRW, uint16_t &outRX, uint16_t &outRY, uint16_t &outRZ, uint16_t &outGW, uint16_t &outGX, uint16_t &outGY, uint16_t &outGZ, uint16_t &outBW, uint16_t &outBX, uint16_t &outBY, uint16_t &outBZ)
{
uint16_t d = 0;
uint16_t rw = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t rz = 0;
uint16_t gw = 0;
uint16_t gx = 0;
uint16_t gy = 0;
uint16_t gz = 0;
uint16_t bw = 0;
uint16_t bx = 0;
uint16_t by = 0;
uint16_t bz = 0;
gy |= ((encoded[0] << 3) & 0x20u);
gz |= ((encoded[0] << 1) & 0x30u);
rw |= ((encoded[0] >> 5) & 0x7fu);
bz |= ((encoded[0] >> 12) & 0x3u);
by |= ((encoded[0] >> 10) & 0x10u);
gw |= ((encoded[0] >> 15) & 0x7fu);
by |= ((encoded[0] >> 17) & 0x20u);
bz |= ((encoded[0] >> 21) & 0x4u);
gy |= ((encoded[0] >> 20) & 0x10u);
bw |= ((encoded[0] >> 25) & 0x7fu);
bz |= ((encoded[1] << 3) & 0x8u);
bz |= ((encoded[1] << 4) & 0x20u);
bz |= ((encoded[1] << 2) & 0x10u);
rx |= ((encoded[1] >> 3) & 0x3fu);
gy |= ((encoded[1] >> 9) & 0xfu);
gx |= ((encoded[1] >> 13) & 0x3fu);
gz |= ((encoded[1] >> 19) & 0xfu);
bx |= ((encoded[1] >> 23) & 0x3fu);
by |= ((encoded[1] >> 29) & 0x7u);
by |= ((encoded[2] << 3) & 0x8u);
ry |= ((encoded[2] >> 1) & 0x3fu);
rz |= ((encoded[2] >> 7) & 0x3fu);
d |= ((encoded[2] >> 13) & 0x1fu);
outD = d;
outRW = rw;
outRX = rx;
outRY = ry;
outRZ = rz;
outGW = gw;
outGX = gx;
outGY = gy;
outGZ = gz;
outBW = bw;
outBX = bx;
outBY = by;
outBZ = bz;
}
void ReadMode2(const uint32_t *encoded, uint16_t &outD, uint16_t &outRW, uint16_t &outRX, uint16_t &outRY, uint16_t &outRZ, uint16_t &outGW, uint16_t &outGX, uint16_t &outGY, uint16_t &outGZ, uint16_t &outBW, uint16_t &outBX, uint16_t &outBY, uint16_t &outBZ)
{
uint16_t d = 0;
uint16_t rw = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t rz = 0;
uint16_t gw = 0;
uint16_t gx = 0;
uint16_t gy = 0;
uint16_t gz = 0;
uint16_t bw = 0;
uint16_t bx = 0;
uint16_t by = 0;
uint16_t bz = 0;
rw |= ((encoded[0] >> 5) & 0x3ffu);
gw |= ((encoded[0] >> 15) & 0x3ffu);
bw |= ((encoded[0] >> 25) & 0x7fu);
bw |= ((encoded[1] << 7) & 0x380u);
rx |= ((encoded[1] >> 3) & 0x1fu);
rw |= ((encoded[1] << 2) & 0x400u);
gy |= ((encoded[1] >> 9) & 0xfu);
gx |= ((encoded[1] >> 13) & 0xfu);
gw |= ((encoded[1] >> 7) & 0x400u);
bz |= ((encoded[1] >> 18) & 0x1u);
gz |= ((encoded[1] >> 19) & 0xfu);
bx |= ((encoded[1] >> 23) & 0xfu);
bw |= ((encoded[1] >> 17) & 0x400u);
bz |= ((encoded[1] >> 27) & 0x2u);
by |= ((encoded[1] >> 29) & 0x7u);
by |= ((encoded[2] << 3) & 0x8u);
ry |= ((encoded[2] >> 1) & 0x1fu);
bz |= ((encoded[2] >> 4) & 0x4u);
rz |= ((encoded[2] >> 7) & 0x1fu);
bz |= ((encoded[2] >> 9) & 0x8u);
d |= ((encoded[2] >> 13) & 0x1fu);
outD = d;
outRW = rw;
outRX = rx;
outRY = ry;
outRZ = rz;
outGW = gw;
outGX = gx;
outGY = gy;
outGZ = gz;
outBW = bw;
outBX = bx;
outBY = by;
outBZ = bz;
}
void ReadMode3(const uint32_t *encoded, uint16_t &outD, uint16_t &outRW, uint16_t &outRX, uint16_t &outRY, uint16_t &outRZ, uint16_t &outGW, uint16_t &outGX, uint16_t &outGY, uint16_t &outGZ, uint16_t &outBW, uint16_t &outBX, uint16_t &outBY, uint16_t &outBZ)
{
uint16_t d = 0;
uint16_t rw = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t rz = 0;
uint16_t gw = 0;
uint16_t gx = 0;
uint16_t gy = 0;
uint16_t gz = 0;
uint16_t bw = 0;
uint16_t bx = 0;
uint16_t by = 0;
uint16_t bz = 0;
rw |= ((encoded[0] >> 5) & 0x3ffu);
gw |= ((encoded[0] >> 15) & 0x3ffu);
bw |= ((encoded[0] >> 25) & 0x7fu);
bw |= ((encoded[1] << 7) & 0x380u);
rx |= ((encoded[1] >> 3) & 0xfu);
rw |= ((encoded[1] << 3) & 0x400u);
gz |= ((encoded[1] >> 4) & 0x10u);
gy |= ((encoded[1] >> 9) & 0xfu);
gx |= ((encoded[1] >> 13) & 0x1fu);
gw |= ((encoded[1] >> 8) & 0x400u);
gz |= ((encoded[1] >> 19) & 0xfu);
bx |= ((encoded[1] >> 23) & 0xfu);
bw |= ((encoded[1] >> 17) & 0x400u);
bz |= ((encoded[1] >> 27) & 0x2u);
by |= ((encoded[1] >> 29) & 0x7u);
by |= ((encoded[2] << 3) & 0x8u);
ry |= ((encoded[2] >> 1) & 0xfu);
bz |= ((encoded[2] >> 5) & 0x1u);
bz |= ((encoded[2] >> 4) & 0x4u);
rz |= ((encoded[2] >> 7) & 0xfu);
gy |= ((encoded[2] >> 7) & 0x10u);
bz |= ((encoded[2] >> 9) & 0x8u);
d |= ((encoded[2] >> 13) & 0x1fu);
outD = d;
outRW = rw;
outRX = rx;
outRY = ry;
outRZ = rz;
outGW = gw;
outGX = gx;
outGY = gy;
outGZ = gz;
outBW = bw;
outBX = bx;
outBY = by;
outBZ = bz;
}
void ReadMode4(const uint32_t *encoded, uint16_t &outD, uint16_t &outRW, uint16_t &outRX, uint16_t &outRY, uint16_t &outRZ, uint16_t &outGW, uint16_t &outGX, uint16_t &outGY, uint16_t &outGZ, uint16_t &outBW, uint16_t &outBX, uint16_t &outBY, uint16_t &outBZ)
{
uint16_t d = 0;
uint16_t rw = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t rz = 0;
uint16_t gw = 0;
uint16_t gx = 0;
uint16_t gy = 0;
uint16_t gz = 0;
uint16_t bw = 0;
uint16_t bx = 0;
uint16_t by = 0;
uint16_t bz = 0;
rw |= ((encoded[0] >> 5) & 0x3ffu);
gw |= ((encoded[0] >> 15) & 0x3ffu);
bw |= ((encoded[0] >> 25) & 0x7fu);
bw |= ((encoded[1] << 7) & 0x380u);
rx |= ((encoded[1] >> 3) & 0xfu);
rw |= ((encoded[1] << 3) & 0x400u);
by |= ((encoded[1] >> 4) & 0x10u);
gy |= ((encoded[1] >> 9) & 0xfu);
gx |= ((encoded[1] >> 13) & 0xfu);
gw |= ((encoded[1] >> 7) & 0x400u);
bz |= ((encoded[1] >> 18) & 0x1u);
gz |= ((encoded[1] >> 19) & 0xfu);
bx |= ((encoded[1] >> 23) & 0x1fu);
bw |= ((encoded[1] >> 18) & 0x400u);
by |= ((encoded[1] >> 29) & 0x7u);
by |= ((encoded[2] << 3) & 0x8u);
ry |= ((encoded[2] >> 1) & 0xfu);
bz |= ((encoded[2] >> 4) & 0x6u);
rz |= ((encoded[2] >> 7) & 0xfu);
bz |= ((encoded[2] >> 7) & 0x10u);
bz |= ((encoded[2] >> 9) & 0x8u);
d |= ((encoded[2] >> 13) & 0x1fu);
outD = d;
outRW = rw;
outRX = rx;
outRY = ry;
outRZ = rz;
outGW = gw;
outGX = gx;
outGY = gy;
outGZ = gz;
outBW = bw;
outBX = bx;
outBY = by;
outBZ = bz;
}
void ReadMode5(const uint32_t *encoded, uint16_t &outD, uint16_t &outRW, uint16_t &outRX, uint16_t &outRY, uint16_t &outRZ, uint16_t &outGW, uint16_t &outGX, uint16_t &outGY, uint16_t &outGZ, uint16_t &outBW, uint16_t &outBX, uint16_t &outBY, uint16_t &outBZ)
{
uint16_t d = 0;
uint16_t rw = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t rz = 0;
uint16_t gw = 0;
uint16_t gx = 0;
uint16_t gy = 0;
uint16_t gz = 0;
uint16_t bw = 0;
uint16_t bx = 0;
uint16_t by = 0;
uint16_t bz = 0;
rw |= ((encoded[0] >> 5) & 0x1ffu);
by |= ((encoded[0] >> 10) & 0x10u);
gw |= ((encoded[0] >> 15) & 0x1ffu);
gy |= ((encoded[0] >> 20) & 0x10u);
bw |= ((encoded[0] >> 25) & 0x7fu);
bw |= ((encoded[1] << 7) & 0x180u);
bz |= ((encoded[1] << 2) & 0x10u);
rx |= ((encoded[1] >> 3) & 0x1fu);
gz |= ((encoded[1] >> 4) & 0x10u);
gy |= ((encoded[1] >> 9) & 0xfu);
gx |= ((encoded[1] >> 13) & 0x1fu);
bz |= ((encoded[1] >> 18) & 0x1u);
gz |= ((encoded[1] >> 19) & 0xfu);
bx |= ((encoded[1] >> 23) & 0x1fu);
bz |= ((encoded[1] >> 27) & 0x2u);
by |= ((encoded[1] >> 29) & 0x7u);
by |= ((encoded[2] << 3) & 0x8u);
ry |= ((encoded[2] >> 1) & 0x1fu);
bz |= ((encoded[2] >> 4) & 0x4u);
rz |= ((encoded[2] >> 7) & 0x1fu);
bz |= ((encoded[2] >> 9) & 0x8u);
d |= ((encoded[2] >> 13) & 0x1fu);
outD = d;
outRW = rw;
outRX = rx;
outRY = ry;
outRZ = rz;
outGW = gw;
outGX = gx;
outGY = gy;
outGZ = gz;
outBW = bw;
outBX = bx;
outBY = by;
outBZ = bz;
}
void ReadMode6(const uint32_t *encoded, uint16_t &outD, uint16_t &outRW, uint16_t &outRX, uint16_t &outRY, uint16_t &outRZ, uint16_t &outGW, uint16_t &outGX, uint16_t &outGY, uint16_t &outGZ, uint16_t &outBW, uint16_t &outBX, uint16_t &outBY, uint16_t &outBZ)
{
uint16_t d = 0;
uint16_t rw = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t rz = 0;
uint16_t gw = 0;
uint16_t gx = 0;
uint16_t gy = 0;
uint16_t gz = 0;
uint16_t bw = 0;
uint16_t bx = 0;
uint16_t by = 0;
uint16_t bz = 0;
rw |= ((encoded[0] >> 5) & 0xffu);
gz |= ((encoded[0] >> 9) & 0x10u);
by |= ((encoded[0] >> 10) & 0x10u);
gw |= ((encoded[0] >> 15) & 0xffu);
bz |= ((encoded[0] >> 21) & 0x4u);
gy |= ((encoded[0] >> 20) & 0x10u);
bw |= ((encoded[0] >> 25) & 0x7fu);
bw |= ((encoded[1] << 7) & 0x80u);
bz |= ((encoded[1] << 2) & 0x18u);
rx |= ((encoded[1] >> 3) & 0x3fu);
gy |= ((encoded[1] >> 9) & 0xfu);
gx |= ((encoded[1] >> 13) & 0x1fu);
bz |= ((encoded[1] >> 18) & 0x1u);
gz |= ((encoded[1] >> 19) & 0xfu);
bx |= ((encoded[1] >> 23) & 0x1fu);
bz |= ((encoded[1] >> 27) & 0x2u);
by |= ((encoded[1] >> 29) & 0x7u);
by |= ((encoded[2] << 3) & 0x8u);
ry |= ((encoded[2] >> 1) & 0x3fu);
rz |= ((encoded[2] >> 7) & 0x3fu);
d |= ((encoded[2] >> 13) & 0x1fu);
outD = d;
outRW = rw;
outRX = rx;
outRY = ry;
outRZ = rz;
outGW = gw;
outGX = gx;
outGY = gy;
outGZ = gz;
outBW = bw;
outBX = bx;
outBY = by;
outBZ = bz;
}
void ReadMode7(const uint32_t *encoded, uint16_t &outD, uint16_t &outRW, uint16_t &outRX, uint16_t &outRY, uint16_t &outRZ, uint16_t &outGW, uint16_t &outGX, uint16_t &outGY, uint16_t &outGZ, uint16_t &outBW, uint16_t &outBX, uint16_t &outBY, uint16_t &outBZ)
{
uint16_t d = 0;
uint16_t rw = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t rz = 0;
uint16_t gw = 0;
uint16_t gx = 0;
uint16_t gy = 0;
uint16_t gz = 0;
uint16_t bw = 0;
uint16_t bx = 0;
uint16_t by = 0;
uint16_t bz = 0;
rw |= ((encoded[0] >> 5) & 0xffu);
bz |= ((encoded[0] >> 13) & 0x1u);
by |= ((encoded[0] >> 10) & 0x10u);
gw |= ((encoded[0] >> 15) & 0xffu);
gy |= ((encoded[0] >> 18) & 0x20u);
gy |= ((encoded[0] >> 20) & 0x10u);
bw |= ((encoded[0] >> 25) & 0x7fu);
bw |= ((encoded[1] << 7) & 0x80u);
gz |= ((encoded[1] << 4) & 0x20u);
bz |= ((encoded[1] << 2) & 0x10u);
rx |= ((encoded[1] >> 3) & 0x1fu);
gz |= ((encoded[1] >> 4) & 0x10u);
gy |= ((encoded[1] >> 9) & 0xfu);
gx |= ((encoded[1] >> 13) & 0x3fu);
gz |= ((encoded[1] >> 19) & 0xfu);
bx |= ((encoded[1] >> 23) & 0x1fu);
bz |= ((encoded[1] >> 27) & 0x2u);
by |= ((encoded[1] >> 29) & 0x7u);
by |= ((encoded[2] << 3) & 0x8u);
ry |= ((encoded[2] >> 1) & 0x1fu);
bz |= ((encoded[2] >> 4) & 0x4u);
rz |= ((encoded[2] >> 7) & 0x1fu);
bz |= ((encoded[2] >> 9) & 0x8u);
d |= ((encoded[2] >> 13) & 0x1fu);
outD = d;
outRW = rw;
outRX = rx;
outRY = ry;
outRZ = rz;
outGW = gw;
outGX = gx;
outGY = gy;
outGZ = gz;
outBW = bw;
outBX = bx;
outBY = by;
outBZ = bz;
}
void ReadMode8(const uint32_t *encoded, uint16_t &outD, uint16_t &outRW, uint16_t &outRX, uint16_t &outRY, uint16_t &outRZ, uint16_t &outGW, uint16_t &outGX, uint16_t &outGY, uint16_t &outGZ, uint16_t &outBW, uint16_t &outBX, uint16_t &outBY, uint16_t &outBZ)
{
uint16_t d = 0;
uint16_t rw = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t rz = 0;
uint16_t gw = 0;
uint16_t gx = 0;
uint16_t gy = 0;
uint16_t gz = 0;
uint16_t bw = 0;
uint16_t bx = 0;
uint16_t by = 0;
uint16_t bz = 0;
rw |= ((encoded[0] >> 5) & 0xffu);
bz |= ((encoded[0] >> 12) & 0x2u);
by |= ((encoded[0] >> 10) & 0x10u);
gw |= ((encoded[0] >> 15) & 0xffu);
by |= ((encoded[0] >> 18) & 0x20u);
gy |= ((encoded[0] >> 20) & 0x10u);
bw |= ((encoded[0] >> 25) & 0x7fu);
bw |= ((encoded[1] << 7) & 0x80u);
bz |= ((encoded[1] << 4) & 0x20u);
bz |= ((encoded[1] << 2) & 0x10u);
rx |= ((encoded[1] >> 3) & 0x1fu);
gz |= ((encoded[1] >> 4) & 0x10u);
gy |= ((encoded[1] >> 9) & 0xfu);
gx |= ((encoded[1] >> 13) & 0x1fu);
bz |= ((encoded[1] >> 18) & 0x1u);
gz |= ((encoded[1] >> 19) & 0xfu);
bx |= ((encoded[1] >> 23) & 0x3fu);
by |= ((encoded[1] >> 29) & 0x7u);
by |= ((encoded[2] << 3) & 0x8u);
ry |= ((encoded[2] >> 1) & 0x1fu);
bz |= ((encoded[2] >> 4) & 0x4u);
rz |= ((encoded[2] >> 7) & 0x1fu);
bz |= ((encoded[2] >> 9) & 0x8u);
d |= ((encoded[2] >> 13) & 0x1fu);
outD = d;
outRW = rw;
outRX = rx;
outRY = ry;
outRZ = rz;
outGW = gw;
outGX = gx;
outGY = gy;
outGZ = gz;
outBW = bw;
outBX = bx;
outBY = by;
outBZ = bz;
}
void ReadMode9(const uint32_t *encoded, uint16_t &outD, uint16_t &outRW, uint16_t &outRX, uint16_t &outRY, uint16_t &outRZ, uint16_t &outGW, uint16_t &outGX, uint16_t &outGY, uint16_t &outGZ, uint16_t &outBW, uint16_t &outBX, uint16_t &outBY, uint16_t &outBZ)
{
uint16_t d = 0;
uint16_t rw = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t rz = 0;
uint16_t gw = 0;
uint16_t gx = 0;
uint16_t gy = 0;
uint16_t gz = 0;
uint16_t bw = 0;
uint16_t bx = 0;
uint16_t by = 0;
uint16_t bz = 0;
rw |= ((encoded[0] >> 5) & 0x3fu);
gz |= ((encoded[0] >> 7) & 0x10u);
bz |= ((encoded[0] >> 12) & 0x3u);
by |= ((encoded[0] >> 10) & 0x10u);
gw |= ((encoded[0] >> 15) & 0x3fu);
gy |= ((encoded[0] >> 16) & 0x20u);
by |= ((encoded[0] >> 17) & 0x20u);
bz |= ((encoded[0] >> 21) & 0x4u);
gy |= ((encoded[0] >> 20) & 0x10u);
bw |= ((encoded[0] >> 25) & 0x3fu);
gz |= ((encoded[0] >> 26) & 0x20u);
bz |= ((encoded[1] << 3) & 0x8u);
bz |= ((encoded[1] << 4) & 0x20u);
bz |= ((encoded[1] << 2) & 0x10u);
rx |= ((encoded[1] >> 3) & 0x3fu);
gy |= ((encoded[1] >> 9) & 0xfu);
gx |= ((encoded[1] >> 13) & 0x3fu);
gz |= ((encoded[1] >> 19) & 0xfu);
bx |= ((encoded[1] >> 23) & 0x3fu);
by |= ((encoded[1] >> 29) & 0x7u);
by |= ((encoded[2] << 3) & 0x8u);
ry |= ((encoded[2] >> 1) & 0x3fu);
rz |= ((encoded[2] >> 7) & 0x3fu);
d |= ((encoded[2] >> 13) & 0x1fu);
outD = d;
outRW = rw;
outRX = rx;
outRY = ry;
outRZ = rz;
outGW = gw;
outGX = gx;
outGY = gy;
outGZ = gz;
outBW = bw;
outBX = bx;
outBY = by;
outBZ = bz;
}
void ReadMode10(const uint32_t *encoded, uint16_t &outD, uint16_t &outRW, uint16_t &outRX, uint16_t &outRY, uint16_t &outRZ, uint16_t &outGW, uint16_t &outGX, uint16_t &outGY, uint16_t &outGZ, uint16_t &outBW, uint16_t &outBX, uint16_t &outBY, uint16_t &outBZ)
{
uint16_t d = 0;
uint16_t rw = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t rz = 0;
uint16_t gw = 0;
uint16_t gx = 0;
uint16_t gy = 0;
uint16_t gz = 0;
uint16_t bw = 0;
uint16_t bx = 0;
uint16_t by = 0;
uint16_t bz = 0;
rw |= ((encoded[0] >> 5) & 0x3ffu);
gw |= ((encoded[0] >> 15) & 0x3ffu);
bw |= ((encoded[0] >> 25) & 0x7fu);
bw |= ((encoded[1] << 7) & 0x380u);
rx |= ((encoded[1] >> 3) & 0x3ffu);
gx |= ((encoded[1] >> 13) & 0x3ffu);
bx |= ((encoded[1] >> 23) & 0x1ffu);
bx |= ((encoded[2] << 9) & 0x200u);
outD = d;
outRW = rw;
outRX = rx;
outRY = ry;
outRZ = rz;
outGW = gw;
outGX = gx;
outGY = gy;
outGZ = gz;
outBW = bw;
outBX = bx;
outBY = by;
outBZ = bz;
}
void ReadMode11(const uint32_t *encoded, uint16_t &outD, uint16_t &outRW, uint16_t &outRX, uint16_t &outRY, uint16_t &outRZ, uint16_t &outGW, uint16_t &outGX, uint16_t &outGY, uint16_t &outGZ, uint16_t &outBW, uint16_t &outBX, uint16_t &outBY, uint16_t &outBZ)
{
uint16_t d = 0;
uint16_t rw = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t rz = 0;
uint16_t gw = 0;
uint16_t gx = 0;
uint16_t gy = 0;
uint16_t gz = 0;
uint16_t bw = 0;
uint16_t bx = 0;
uint16_t by = 0;
uint16_t bz = 0;
rw |= ((encoded[0] >> 5) & 0x3ffu);
gw |= ((encoded[0] >> 15) & 0x3ffu);
bw |= ((encoded[0] >> 25) & 0x7fu);
bw |= ((encoded[1] << 7) & 0x380u);
rx |= ((encoded[1] >> 3) & 0x1ffu);
rw |= ((encoded[1] >> 2) & 0x400u);
gx |= ((encoded[1] >> 13) & 0x1ffu);
gw |= ((encoded[1] >> 12) & 0x400u);
bx |= ((encoded[1] >> 23) & 0x1ffu);
bw |= ((encoded[2] << 10) & 0x400u);
outD = d;
outRW = rw;
outRX = rx;
outRY = ry;
outRZ = rz;
outGW = gw;
outGX = gx;
outGY = gy;
outGZ = gz;
outBW = bw;
outBX = bx;
outBY = by;
outBZ = bz;
}
void ReadMode12(const uint32_t *encoded, uint16_t &outD, uint16_t &outRW, uint16_t &outRX, uint16_t &outRY, uint16_t &outRZ, uint16_t &outGW, uint16_t &outGX, uint16_t &outGY, uint16_t &outGZ, uint16_t &outBW, uint16_t &outBX, uint16_t &outBY, uint16_t &outBZ)
{
uint16_t d = 0;
uint16_t rw = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t rz = 0;
uint16_t gw = 0;
uint16_t gx = 0;
uint16_t gy = 0;
uint16_t gz = 0;
uint16_t bw = 0;
uint16_t bx = 0;
uint16_t by = 0;
uint16_t bz = 0;
rw |= ((encoded[0] >> 5) & 0x3ffu);
gw |= ((encoded[0] >> 15) & 0x3ffu);
bw |= ((encoded[0] >> 25) & 0x7fu);
bw |= ((encoded[1] << 7) & 0x380u);
rx |= ((encoded[1] >> 3) & 0xffu);
rw |= (encoded[1] & 0x800u);
rw |= ((encoded[1] >> 2) & 0x400u);
gx |= ((encoded[1] >> 13) & 0xffu);
gw |= ((encoded[1] >> 10) & 0x800u);
gw |= ((encoded[1] >> 12) & 0x400u);
bx |= ((encoded[1] >> 23) & 0xffu);
bw |= ((encoded[1] >> 20) & 0x800u);
bw |= ((encoded[2] << 10) & 0x400u);
outD = d;
outRW = rw;
outRX = rx;
outRY = ry;
outRZ = rz;
outGW = gw;
outGX = gx;
outGY = gy;
outGZ = gz;
outBW = bw;
outBX = bx;
outBY = by;
outBZ = bz;
}
void ReadMode13(const uint32_t *encoded, uint16_t &outD, uint16_t &outRW, uint16_t &outRX, uint16_t &outRY, uint16_t &outRZ, uint16_t &outGW, uint16_t &outGX, uint16_t &outGY, uint16_t &outGZ, uint16_t &outBW, uint16_t &outBX, uint16_t &outBY, uint16_t &outBZ)
{
uint16_t d = 0;
uint16_t rw = 0;
uint16_t rx = 0;
uint16_t ry = 0;
uint16_t rz = 0;
uint16_t gw = 0;
uint16_t gx = 0;
uint16_t gy = 0;
uint16_t gz = 0;
uint16_t bw = 0;
uint16_t bx = 0;
uint16_t by = 0;
uint16_t bz = 0;
rw |= ((encoded[0] >> 5) & 0x3ffu);
gw |= ((encoded[0] >> 15) & 0x3ffu);
bw |= ((encoded[0] >> 25) & 0x7fu);
bw |= ((encoded[1] << 7) & 0x380u);
rx |= ((encoded[1] >> 3) & 0xfu);
rw |= ((encoded[1] << 8) & 0x8000u);
rw |= ((encoded[1] << 6) & 0x4000u);
rw |= ((encoded[1] << 4) & 0x2000u);
rw |= ((encoded[1] << 2) & 0x1000u);
rw |= (encoded[1] & 0x800u);
rw |= ((encoded[1] >> 2) & 0x400u);
gx |= ((encoded[1] >> 13) & 0xfu);
gw |= ((encoded[1] >> 2) & 0x8000u);
gw |= ((encoded[1] >> 4) & 0x4000u);
gw |= ((encoded[1] >> 6) & 0x2000u);
gw |= ((encoded[1] >> 8) & 0x1000u);
gw |= ((encoded[1] >> 10) & 0x800u);
gw |= ((encoded[1] >> 12) & 0x400u);
bx |= ((encoded[1] >> 23) & 0xfu);
bw |= ((encoded[1] >> 12) & 0x8000u);
bw |= ((encoded[1] >> 14) & 0x4000u);
bw |= ((encoded[1] >> 16) & 0x2000u);
bw |= ((encoded[1] >> 18) & 0x1000u);
bw |= ((encoded[1] >> 20) & 0x800u);
bw |= ((encoded[2] << 10) & 0x400u);
outD = d;
outRW = rw;
outRX = rx;
outRY = ry;
outRZ = rz;
outGW = gw;
outGX = gx;
outGY = gy;
outGZ = gz;
outBW = bw;
outBX = bx;
outBY = by;
outBZ = bz;
}
const ReadFunc_t g_readFuncs[14] =
{
ReadMode0,
ReadMode1,
ReadMode2,
ReadMode3,
ReadMode4,
ReadMode5,
ReadMode6,
ReadMode7,
ReadMode8,
ReadMode9,
ReadMode10,
ReadMode11,
ReadMode12,
ReadMode13
};
const WriteFunc_t g_writeFuncs[14] =
{
WriteMode0,
WriteMode1,
WriteMode2,
WriteMode3,
WriteMode4,
WriteMode5,
WriteMode6,
WriteMode7,
WriteMode8,
WriteMode9,
WriteMode10,
WriteMode11,
WriteMode12,
WriteMode13
};
}
}
#endif

View File

@@ -0,0 +1,16 @@
#pragma once
#include <stdint.h>
#include "ConvectionKernels_BC6H_IO.h"
namespace cvtt
{
namespace BC6H_IO
{
typedef void (*ReadFunc_t)(const uint32_t *encoded, uint16_t &d, uint16_t &rw, uint16_t &rx, uint16_t &ry, uint16_t &rz, uint16_t &gw, uint16_t &gx, uint16_t &gy, uint16_t &gz, uint16_t &bw, uint16_t &bx, uint16_t &by, uint16_t &bz);
typedef void (*WriteFunc_t)(uint32_t *encoded, uint16_t m, uint16_t d, uint16_t rw, uint16_t rx, uint16_t ry, uint16_t rz, uint16_t gw, uint16_t gx, uint16_t gy, uint16_t gz, uint16_t bw, uint16_t bx, uint16_t by, uint16_t bz);
extern const ReadFunc_t g_readFuncs[14];
extern const WriteFunc_t g_writeFuncs[14];
}
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include <stdint.h>
namespace cvtt { namespace Tables { namespace BC7Prio {
extern const uint16_t *g_bc7PrioCodesRGB;
extern const int g_bc7NumPrioCodesRGB;
extern const uint16_t *g_bc7PrioCodesRGBA;
extern const int g_bc7NumPrioCodesRGBA;
int UnpackMode(uint16_t packed);
int UnpackSeedPointCount(uint16_t packed);
int UnpackPartition(uint16_t packed);
int UnpackRotation(uint16_t packed);
int UnpackIndexSelector(uint16_t packed);
}}}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
/*
Convection Texture Tools
Copyright (c) 2018-2019 Eric Lasota
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.
-------------------------------------------------------------------------------------
Portions based on DirectX Texture Library (DirectXTex)
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
http://go.microsoft.com/fwlink/?LinkId=248926
*/
#include "ConvectionKernels_Config.h"
#if !defined(CVTT_SINGLE_FILE) || defined(CVTT_SINGLE_FILE_IMPL)
#include "ConvectionKernels_BCCommon.h"
int cvtt::Internal::BCCommon::TweakRoundsForRange(int range)
{
if (range == 3)
return 3;
return 4;
}
#endif

View File

@@ -0,0 +1,104 @@
#pragma once
#ifndef __CVTT_BCCOMMON_H__
#define __CVTT_BCCOMMON_H__
#include "ConvectionKernels_AggregatedError.h"
#include "ConvectionKernels_ParallelMath.h"
namespace cvtt
{
namespace Internal
{
class BCCommon
{
public:
typedef ParallelMath::Float MFloat;
typedef ParallelMath::UInt16 MUInt16;
typedef ParallelMath::UInt15 MUInt15;
typedef ParallelMath::AInt16 MAInt16;
typedef ParallelMath::SInt16 MSInt16;
typedef ParallelMath::SInt32 MSInt32;
static int TweakRoundsForRange(int range);
template<int TVectorSize>
static void ComputeErrorLDR(uint32_t flags, const MUInt15 reconstructed[TVectorSize], const MUInt15 original[TVectorSize], int numRealChannels, AggregatedError<TVectorSize> &aggError)
{
for (int ch = 0; ch < numRealChannels; ch++)
aggError.Add(ParallelMath::SqDiffUInt8(reconstructed[ch], original[ch]), ch);
}
template<int TVectorSize>
static void ComputeErrorLDR(uint32_t flags, const MUInt15 reconstructed[TVectorSize], const MUInt15 original[TVectorSize], AggregatedError<TVectorSize> &aggError)
{
ComputeErrorLDR<TVectorSize>(flags, reconstructed, original, TVectorSize, aggError);
}
template<int TVectorSize>
static MFloat ComputeErrorLDRSimple(uint32_t flags, const MUInt15 reconstructed[TVectorSize], const MUInt15 original[TVectorSize], int numRealChannels, const float *channelWeightsSq)
{
AggregatedError<TVectorSize> aggError;
ComputeErrorLDR<TVectorSize>(flags, reconstructed, original, numRealChannels, aggError);
return aggError.Finalize(flags, channelWeightsSq);
}
template<int TVectorSize>
static MFloat ComputeErrorHDRFast(uint32_t flags, const MSInt16 reconstructed[TVectorSize], const MSInt16 original[TVectorSize], const float channelWeightsSq[TVectorSize])
{
MFloat error = ParallelMath::MakeFloatZero();
if (flags & Flags::Uniform)
{
for (int ch = 0; ch < TVectorSize; ch++)
error = error + ParallelMath::SqDiffSInt16(reconstructed[ch], original[ch]);
}
else
{
for (int ch = 0; ch < TVectorSize; ch++)
error = error + ParallelMath::SqDiffSInt16(reconstructed[ch], original[ch]) * ParallelMath::MakeFloat(channelWeightsSq[ch]);
}
return error;
}
template<int TVectorSize>
static MFloat ComputeErrorHDRSlow(uint32_t flags, const MSInt16 reconstructed[TVectorSize], const MSInt16 original[TVectorSize], const float channelWeightsSq[TVectorSize])
{
MFloat error = ParallelMath::MakeFloatZero();
if (flags & Flags::Uniform)
{
for (int ch = 0; ch < TVectorSize; ch++)
error = error + ParallelMath::SqDiff2CL(reconstructed[ch], original[ch]);
}
else
{
for (int ch = 0; ch < TVectorSize; ch++)
error = error + ParallelMath::SqDiff2CL(reconstructed[ch], original[ch]) * ParallelMath::MakeFloat(channelWeightsSq[ch]);
}
return error;
}
template<int TChannelCount>
static void PreWeightPixelsLDR(MFloat preWeightedPixels[16][TChannelCount], const MUInt15 pixels[16][TChannelCount], const float channelWeights[TChannelCount])
{
for (int px = 0; px < 16; px++)
{
for (int ch = 0; ch < TChannelCount; ch++)
preWeightedPixels[px][ch] = ParallelMath::ToFloat(pixels[px][ch]) * channelWeights[ch];
}
}
template<int TChannelCount>
static void PreWeightPixelsHDR(MFloat preWeightedPixels[16][TChannelCount], const MSInt16 pixels[16][TChannelCount], const float channelWeights[TChannelCount])
{
for (int px = 0; px < 16; px++)
{
for (int ch = 0; ch < TChannelCount; ch++)
preWeightedPixels[px][ch] = ParallelMath::ToFloat(pixels[px][ch]) * channelWeights[ch];
}
}
};
}
}
#endif

View File

@@ -0,0 +1,12 @@
#pragma once
#ifndef __CVTT_CONFIG_H__
#define __CVTT_CONFIG_H__
#if (defined(_M_IX86_FP) && _M_IX86_FP >= 2) || defined(_M_X64) || defined(__SSE2__)
#define CVTT_USE_SSE2
#endif
// Define this to compile everything as a single source file
//#define CVTT_SINGLE_FILE
#endif

3147
thirdparty/cvtt/ConvectionKernels_ETC.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

126
thirdparty/cvtt/ConvectionKernels_ETC.h vendored Normal file
View File

@@ -0,0 +1,126 @@
#pragma once
#ifndef __CVTT_CONVECTIONKERNELS_ETC_H__
#define __CVTT_CONVECTIONKERNELS_ETC_H__
#include "ConvectionKernels.h"
#include "ConvectionKernels_ParallelMath.h"
namespace cvtt
{
struct Options;
namespace Internal
{
class ETCComputer
{
public:
static void CompressETC1Block(uint8_t *outputBuffer, const PixelBlockU8 *inputBlocks, ETC1CompressionData *compressionData, const Options &options);
static void CompressETC2Block(uint8_t *outputBuffer, const PixelBlockU8 *inputBlocks, ETC2CompressionData *compressionData, const Options &options, bool punchthroughAlpha);
static void CompressETC2AlphaBlock(uint8_t *outputBuffer, const PixelBlockU8 *inputBlocks, const Options &options);
static void CompressEACBlock(uint8_t *outputBuffer, const PixelBlockScalarS16 *inputBlocks, bool isSigned, const Options &options);
static ETC2CompressionData *AllocETC2Data(cvtt::Kernels::allocFunc_t allocFunc, void *context, const cvtt::Options &options);
static void ReleaseETC2Data(ETC2CompressionData *compressionData, cvtt::Kernels::freeFunc_t freeFunc);
static ETC1CompressionData *AllocETC1Data(cvtt::Kernels::allocFunc_t allocFunc, void *context);
static void ReleaseETC1Data(ETC1CompressionData *compressionData, cvtt::Kernels::freeFunc_t freeFunc);
private:
typedef ParallelMath::Float MFloat;
typedef ParallelMath::SInt16 MSInt16;
typedef ParallelMath::UInt15 MUInt15;
typedef ParallelMath::UInt16 MUInt16;
typedef ParallelMath::SInt32 MSInt32;
typedef ParallelMath::UInt31 MUInt31;
struct DifferentialResolveStorage
{
static const unsigned int MaxAttemptsPerSector = 57 + 81 + 81 + 81 + 81 + 81 + 81 + 81;
MUInt15 diffNumAttempts[2];
MFloat diffErrors[2][MaxAttemptsPerSector];
MUInt16 diffSelectors[2][MaxAttemptsPerSector];
MUInt15 diffColors[2][MaxAttemptsPerSector];
MUInt15 diffTables[2][MaxAttemptsPerSector];
uint16_t attemptSortIndexes[2][MaxAttemptsPerSector];
};
struct HModeEval
{
MFloat errors[62][16];
MUInt16 signBits[62];
MUInt15 uniqueQuantizedColors[62];
MUInt15 numUniqueColors[2];
};
struct ETC1CompressionDataInternal : public cvtt::ETC1CompressionData
{
explicit ETC1CompressionDataInternal(void *context)
: m_context(context)
{
}
DifferentialResolveStorage m_drs;
void *m_context;
};
struct ETC2CompressionDataInternal : public cvtt::ETC2CompressionData
{
explicit ETC2CompressionDataInternal(void *context, const cvtt::Options &options);
HModeEval m_h;
DifferentialResolveStorage m_drs;
void *m_context;
float m_chromaSideAxis0[3];
float m_chromaSideAxis1[3];
};
static MFloat ComputeErrorUniform(const MUInt15 pixelA[3], const MUInt15 pixelB[3]);
static MFloat ComputeErrorWeighted(const MUInt15 reconstructed[3], const MFloat pixelB[3], const Options options);
static MFloat ComputeErrorFakeBT709(const MUInt15 reconstructed[3], const MFloat pixelB[3]);
static void TestHalfBlock(MFloat &outError, MUInt16 &outSelectors, MUInt15 quantizedPackedColor, const MUInt15 pixels[8][3], const MFloat preWeightedPixels[8][3], const MSInt16 modifiers[4], bool isDifferential, const Options &options);
static void TestHalfBlockPunchthrough(MFloat &outError, MUInt16 &outSelectors, MUInt15 quantizedPackedColor, const MUInt15 pixels[8][3], const MFloat preWeightedPixels[8][3], const ParallelMath::Int16CompFlag isTransparent[8], const MUInt15 modifier, const Options &options);
static void FindBestDifferentialCombination(int flip, int d, const ParallelMath::Int16CompFlag canIgnoreSector[2], ParallelMath::Int16CompFlag& bestIsThisMode, MFloat& bestTotalError, MUInt15& bestFlip, MUInt15& bestD, MUInt15 bestColors[2], MUInt16 bestSelectors[2], MUInt15 bestTables[2], DifferentialResolveStorage &drs);
static ParallelMath::Int16CompFlag ETCDifferentialIsLegalForChannel(const MUInt15 &a, const MUInt15 &b);
static ParallelMath::Int16CompFlag ETCDifferentialIsLegal(const MUInt15 &a, const MUInt15 &b);
static bool ETCDifferentialIsLegalForChannelScalar(const uint16_t &a, const uint16_t &b);
static bool ETCDifferentialIsLegalScalar(const uint16_t &a, const uint16_t &b);
static void EncodeTMode(uint8_t *outputBuffer, MFloat &bestError, const ParallelMath::Int16CompFlag isIsolated[16], const MUInt15 pixels[16][3], const MFloat preWeightedPixels[16][3], const Options &options);
static void EncodeHMode(uint8_t *outputBuffer, MFloat &bestError, const ParallelMath::Int16CompFlag groupings[16], const MUInt15 pixels[16][3], HModeEval &he, const MFloat preWeightedPixels[16][3], const Options &options);
static void EncodeVirtualTModePunchthrough(uint8_t *outputBuffer, MFloat &bestError, const ParallelMath::Int16CompFlag isIsolated[16], const MUInt15 pixels[16][3], const MFloat preWeightedPixels[16][3], const ParallelMath::Int16CompFlag isTransparent[16], const ParallelMath::Int16CompFlag& anyTransparent, const ParallelMath::Int16CompFlag& allTransparent, const Options &options);
static MUInt15 DecodePlanarCoeff(const MUInt15 &coeff, int ch);
static void EncodePlanar(uint8_t *outputBuffer, MFloat &bestError, const MUInt15 pixels[16][3], const MFloat preWeightedPixels[16][3], const Options &options);
static void CompressETC1BlockInternal(MFloat &bestTotalError, uint8_t *outputBuffer, const MUInt15 pixels[16][3], const MFloat preWeightedPixels[16][3], DifferentialResolveStorage& compressionData, const Options &options, bool punchthrough);
static void CompressETC1PunchthroughBlockInternal(MFloat &bestTotalError, uint8_t *outputBuffer, const MUInt15 pixels[16][3], const MFloat preWeightedPixels[16][3], const ParallelMath::Int16CompFlag isTransparent[16], DifferentialResolveStorage& compressionData, const Options &options);
static void CompressETC2AlphaBlockInternal(uint8_t *outputBuffer, const MUInt15 pixels[16], bool is11Bit, bool isSigned, const Options &options);
static void ExtractBlocks(MUInt15 pixels[16][3], MFloat preWeightedPixels[16][3], const PixelBlockU8 *inputBlocks, const Options &options);
static void ResolveHalfBlockFakeBT709RoundingAccurate(MUInt15 quantized[3], const MUInt15 sectorCumulative[3], bool isDifferential);
static void ResolveHalfBlockFakeBT709RoundingFast(MUInt15 quantized[3], const MUInt15 sectorCumulative[3], bool isDifferential);
static void ResolveTHFakeBT709Rounding(MUInt15 quantized[3], const MUInt15 target[3], const MUInt15 &granularity);
static void ConvertToFakeBT709(MFloat yuv[3], const MUInt15 color[3]);
static void ConvertToFakeBT709(MFloat yuv[3], const MFloat color[3]);
static void ConvertToFakeBT709(MFloat yuv[3], const MFloat &r, const MFloat &g, const MFloat &b);
static void ConvertFromFakeBT709(MFloat rgb[3], const MFloat yuv[3]);
static void QuantizeETC2Alpha(int tableIndex, const MUInt15& value, const MUInt15& baseValue, const MUInt15& multiplier, bool is11Bit, bool isSigned, MUInt15& outIndexes, MUInt15& outQuantizedValues);
static void EmitTModeBlock(uint8_t *outputBuffer, const ParallelMath::ScalarUInt16 lineColor[3], const ParallelMath::ScalarUInt16 isolatedColor[3], int32_t packedSelectors, ParallelMath::ScalarUInt16 table, bool opaque);
static void EmitHModeBlock(uint8_t *outputBuffer, const ParallelMath::ScalarUInt16 blockColors[2], ParallelMath::ScalarUInt16 sectorBits, ParallelMath::ScalarUInt16 signBits, ParallelMath::ScalarUInt16 table, bool opaque);
static void EmitETC1Block(uint8_t *outputBuffer, int blockBestFlip, int blockBestD, const int blockBestColors[2][3], const int blockBestTables[2], const ParallelMath::ScalarUInt16 blockBestSelectors[2], bool transparent);
static const int g_flipTables[2][2][8];
};
}
}
#endif

View File

@@ -0,0 +1,29 @@
#include <stdint.h>
namespace cvtt
{
namespace Tables
{
namespace ETC1
{
const int16_t g_potentialOffsets4[] =
{
57, -64, -58, -54, -52, -48, -46, -44, -42, -40, -38, -36, -34, -32, -30, -28, -26, -24, -22, -20, -18, -16, -14, -12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 52, 54, 58, 64,
81, -136, -124, -114, -112, -102, -100, -92, -90, -88, -80, -78, -76, -70, -68, -66, -64, -58, -56, -54, -52, -48, -46, -44, -42, -40, -36, -34, -32, -30, -26, -24, -22, -20, -18, -14, -12, -10, -8, -4, -2, 0, 2, 4, 8, 10, 12, 14, 18, 20, 22, 24, 26, 30, 32, 34, 36, 40, 42, 44, 46, 48, 52, 54, 56, 58, 64, 66, 68, 70, 76, 78, 80, 88, 90, 92, 100, 102, 112, 114, 124, 136,
81, -232, -212, -194, -192, -174, -172, -156, -154, -152, -136, -134, -132, -118, -116, -114, -112, -98, -96, -94, -92, -80, -78, -76, -74, -72, -60, -58, -56, -54, -42, -40, -38, -36, -34, -22, -20, -18, -16, -4, -2, 0, 2, 4, 16, 18, 20, 22, 34, 36, 38, 40, 42, 54, 56, 58, 60, 72, 74, 76, 78, 80, 92, 94, 96, 98, 112, 114, 116, 118, 132, 134, 136, 152, 154, 156, 172, 174, 192, 194, 212, 232,
81, -336, -307, -281, -278, -252, -249, -226, -223, -220, -197, -194, -191, -171, -168, -165, -162, -142, -139, -136, -133, -116, -113, -110, -107, -104, -87, -84, -81, -78, -61, -58, -55, -52, -49, -32, -29, -26, -23, -6, -3, 0, 3, 6, 23, 26, 29, 32, 49, 52, 55, 58, 61, 78, 81, 84, 87, 104, 107, 110, 113, 116, 133, 136, 139, 142, 162, 165, 168, 171, 191, 194, 197, 220, 223, 226, 249, 252, 278, 281, 307, 336,
81, -480, -438, -402, -396, -360, -354, -324, -318, -312, -282, -276, -270, -246, -240, -234, -228, -204, -198, -192, -186, -168, -162, -156, -150, -144, -126, -120, -114, -108, -90, -84, -78, -72, -66, -48, -42, -36, -30, -12, -6, 0, 6, 12, 30, 36, 42, 48, 66, 72, 78, 84, 90, 108, 114, 120, 126, 144, 150, 156, 162, 168, 186, 192, 198, 204, 228, 234, 240, 246, 270, 276, 282, 312, 318, 324, 354, 360, 396, 402, 438, 480,
81, -640, -584, -536, -528, -480, -472, -432, -424, -416, -376, -368, -360, -328, -320, -312, -304, -272, -264, -256, -248, -224, -216, -208, -200, -192, -168, -160, -152, -144, -120, -112, -104, -96, -88, -64, -56, -48, -40, -16, -8, 0, 8, 16, 40, 48, 56, 64, 88, 96, 104, 112, 120, 144, 152, 160, 168, 192, 200, 208, 216, 224, 248, 256, 264, 272, 304, 312, 320, 328, 360, 368, 376, 416, 424, 432, 472, 480, 528, 536, 584, 640,
81, -848, -775, -709, -702, -636, -629, -570, -563, -556, -497, -490, -483, -431, -424, -417, -410, -358, -351, -344, -337, -292, -285, -278, -271, -264, -219, -212, -205, -198, -153, -146, -139, -132, -125, -80, -73, -66, -59, -14, -7, 0, 7, 14, 59, 66, 73, 80, 125, 132, 139, 146, 153, 198, 205, 212, 219, 264, 271, 278, 285, 292, 337, 344, 351, 358, 410, 417, 424, 431, 483, 490, 497, 556, 563, 570, 629, 636, 702, 709, 775, 848,
81, -1464, -1328, -1234, -1192, -1098, -1056, -1004, -962, -920, -868, -826, -784, -774, -732, -690, -648, -638, -596, -554, -544, -512, -502, -460, -418, -408, -376, -366, -324, -314, -282, -272, -230, -188, -178, -146, -136, -94, -84, -52, -42, 0, 42, 52, 84, 94, 136, 146, 178, 188, 230, 272, 282, 314, 324, 366, 376, 408, 418, 460, 502, 512, 544, 554, 596, 638, 648, 690, 732, 774, 784, 826, 868, 920, 962, 1004, 1056, 1098, 1192, 1234, 1328, 1464
};
const unsigned int g_maxPotentialOffsets = 81;
const int16_t g_thModifierTable[8] =
{
3, 6, 11, 16, 23, 32, 41, 64
};
}
}
}

View File

@@ -0,0 +1,35 @@
#include <stdint.h>
namespace cvtt
{
namespace Tables
{
namespace ETC2
{
const int16_t g_thModifierTable[8] =
{
3, 6, 11, 16, 23, 32, 41, 64
};
const int16_t g_alphaModifierTablePositive[16][4] =
{
{ 2, 5, 8, 14, },
{ 2, 6, 9, 12, },
{ 1, 4, 7, 12, },
{ 1, 3, 5, 12, },
{ 2, 5, 7, 11, },
{ 2, 6, 8, 10, },
{ 3, 6, 7, 10, },
{ 2, 4, 7, 10, },
{ 1, 5, 7, 9, },
{ 1, 4, 7, 9, },
{ 1, 3, 7, 9, },
{ 1, 4, 6, 9, },
{ 2, 3, 6, 9, },
{ 0, 1, 2, 9, },
{ 3, 5, 7, 8, },
{ 2, 4, 6, 8, },
};
}
}
}

View File

@@ -0,0 +1,27 @@
#pragma once
#include <stdint.h>
// This file is generated by the MakeTables app. Do not edit this file manually.
namespace cvtt { namespace Tables { namespace ETC2 {
const int g_alphaRoundingTableWidth = 13;
const uint8_t g_alphaRoundingTables[16][13] =
{
{ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3 },
{ 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3 },
{ 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3 },
{ 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 },
{ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3 },
{ 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3 },
{ 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3 },
{ 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3 },
{ 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3 },
{ 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3 },
{ 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3 },
{ 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3 },
{ 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3 },
{ 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3 },
{ 0, 0, 0, 0, 0, 1, 1, 2, 3, 3, 3, 3, 3 },
{ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3 },
};
}}}

View File

@@ -0,0 +1,181 @@
#pragma once
#ifndef __CVTT_ENDPOINTREFINER_H__
#define __CVTT_ENDPOINTREFINER_H__
#include "ConvectionKernels_ParallelMath.h"
namespace cvtt
{
namespace Internal
{
// Solve for a, b where v = a*t + b
// This allows endpoints to be mapped to where T=0 and T=1
// Least squares from totals:
// a = (tv - t*v/w)/(tt - t*t/w)
// b = (v - a*t)/w
template<int TVectorSize>
class EndpointRefiner
{
public:
typedef ParallelMath::Float MFloat;
typedef ParallelMath::UInt16 MUInt16;
typedef ParallelMath::UInt15 MUInt15;
typedef ParallelMath::AInt16 MAInt16;
typedef ParallelMath::SInt16 MSInt16;
typedef ParallelMath::SInt32 MSInt32;
MFloat m_tv[TVectorSize];
MFloat m_v[TVectorSize];
MFloat m_tt;
MFloat m_t;
MFloat m_w;
int m_wu;
float m_rcpMaxIndex;
float m_channelWeights[TVectorSize];
float m_rcpChannelWeights[TVectorSize];
void Init(int indexRange, const float channelWeights[TVectorSize])
{
for (int ch = 0; ch < TVectorSize; ch++)
{
m_tv[ch] = ParallelMath::MakeFloatZero();
m_v[ch] = ParallelMath::MakeFloatZero();
}
m_tt = ParallelMath::MakeFloatZero();
m_t = ParallelMath::MakeFloatZero();
m_w = ParallelMath::MakeFloatZero();
m_rcpMaxIndex = 1.0f / static_cast<float>(indexRange - 1);
for (int ch = 0; ch < TVectorSize; ch++)
{
m_channelWeights[ch] = channelWeights[ch];
m_rcpChannelWeights[ch] = 1.0f;
if (m_channelWeights[ch] != 0.0f)
m_rcpChannelWeights[ch] = 1.0f / channelWeights[ch];
}
m_wu = 0;
}
void ContributePW(const MFloat *pwFloatPixel, const MUInt15 &index, const MFloat &weight)
{
MFloat t = ParallelMath::ToFloat(index) * m_rcpMaxIndex;
for (int ch = 0; ch < TVectorSize; ch++)
{
MFloat v = pwFloatPixel[ch] * weight;
m_tv[ch] = m_tv[ch] + t * v;
m_v[ch] = m_v[ch] + v;
}
m_tt = m_tt + weight * t * t;
m_t = m_t + weight * t;
m_w = m_w + weight;
}
void ContributeUnweightedPW(const MFloat *pwFloatPixel, const MUInt15 &index, int numRealChannels)
{
MFloat t = ParallelMath::ToFloat(index) * m_rcpMaxIndex;
for (int ch = 0; ch < numRealChannels; ch++)
{
MFloat v = pwFloatPixel[ch];
m_tv[ch] = m_tv[ch] + t * v;
m_v[ch] = m_v[ch] + v;
}
m_tt = m_tt + t * t;
m_t = m_t + t;
m_wu++;
}
void ContributeUnweightedPW(const MFloat *floatPixel, const MUInt15 &index)
{
ContributeUnweightedPW(floatPixel, index, TVectorSize);
}
void GetRefinedEndpoints(MFloat endPoint[2][TVectorSize])
{
// a = (tv - t*v/w)/(tt - t*t/w)
// b = (v - a*t)/w
MFloat w = m_w + ParallelMath::MakeFloat(static_cast<float>(m_wu));
ParallelMath::MakeSafeDenominator(w);
MFloat wRcp = ParallelMath::Reciprocal(w);
MFloat adenom = (m_tt * w - m_t * m_t) * wRcp;
ParallelMath::FloatCompFlag adenomZero = ParallelMath::Equal(adenom, ParallelMath::MakeFloatZero());
ParallelMath::ConditionalSet(adenom, adenomZero, ParallelMath::MakeFloat(1.0f));
for (int ch = 0; ch < TVectorSize; ch++)
{
/*
if (adenom == 0.0)
p1 = p2 = er.v / er.w;
else
{
float4 a = (er.tv - er.t*er.v / er.w) / adenom;
float4 b = (er.v - a * er.t) / er.w;
p1 = b;
p2 = a + b;
}
*/
MFloat a = (m_tv[ch] - m_t * m_v[ch] * wRcp) / adenom;
MFloat b = (m_v[ch] - a * m_t) * wRcp;
MFloat p1 = b;
MFloat p2 = a + b;
ParallelMath::ConditionalSet(p1, adenomZero, (m_v[ch] * wRcp));
ParallelMath::ConditionalSet(p2, adenomZero, p1);
// Unweight
float inverseWeight = m_rcpChannelWeights[ch];
endPoint[0][ch] = p1 * inverseWeight;
endPoint[1][ch] = p2 * inverseWeight;
}
}
void GetRefinedEndpointsLDR(MUInt15 endPoint[2][TVectorSize], int numRealChannels, const ParallelMath::RoundTowardNearestForScope *roundingMode)
{
MFloat floatEndPoint[2][TVectorSize];
GetRefinedEndpoints(floatEndPoint);
for (int epi = 0; epi < 2; epi++)
for (int ch = 0; ch < TVectorSize; ch++)
endPoint[epi][ch] = ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(floatEndPoint[epi][ch], 0.0f, 255.0f), roundingMode);
}
void GetRefinedEndpointsLDR(MUInt15 endPoint[2][TVectorSize], const ParallelMath::RoundTowardNearestForScope *roundingMode)
{
GetRefinedEndpointsLDR(endPoint, TVectorSize, roundingMode);
}
void GetRefinedEndpointsHDR(MSInt16 endPoint[2][TVectorSize], bool isSigned, const ParallelMath::RoundTowardNearestForScope *roundingMode)
{
MFloat floatEndPoint[2][TVectorSize];
GetRefinedEndpoints(floatEndPoint);
for (int epi = 0; epi < 2; epi++)
{
for (int ch = 0; ch < TVectorSize; ch++)
{
MFloat f = floatEndPoint[epi][ch];
if (isSigned)
endPoint[epi][ch] = ParallelMath::LosslessCast<MSInt16>::Cast(ParallelMath::RoundAndConvertToS16(ParallelMath::Clamp(f, -31743.0f, 31743.0f), roundingMode));
else
endPoint[epi][ch] = ParallelMath::LosslessCast<MSInt16>::Cast(ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(f, 0.0f, 31743.0f), roundingMode));
}
}
}
};
}
}
#endif

View File

@@ -0,0 +1,153 @@
#pragma once
#ifndef __CVTT_ENDPOINTSELECTOR_H__
#define __CVTT_ENDPOINTSELECTOR_H__
#include "ConvectionKernels_ParallelMath.h"
#include "ConvectionKernels_UnfinishedEndpoints.h"
#include "ConvectionKernels_PackedCovarianceMatrix.h"
namespace cvtt
{
namespace Internal
{
static const int NumEndpointSelectorPasses = 3;
template<int TVectorSize, int TIterationCount>
class EndpointSelector
{
public:
typedef ParallelMath::Float MFloat;
EndpointSelector()
{
for (int ch = 0; ch < TVectorSize; ch++)
{
m_centroid[ch] = ParallelMath::MakeFloatZero();
m_direction[ch] = ParallelMath::MakeFloatZero();
}
m_weightTotal = ParallelMath::MakeFloatZero();
m_minDist = ParallelMath::MakeFloat(FLT_MAX);
m_maxDist = ParallelMath::MakeFloat(-FLT_MAX);
}
void ContributePass(const MFloat *value, int pass, const MFloat &weight)
{
if (pass == 0)
ContributeCentroid(value, weight);
else if (pass == 1)
ContributeDirection(value, weight);
else if (pass == 2)
ContributeMinMax(value);
}
void FinishPass(int pass)
{
if (pass == 0)
FinishCentroid();
else if (pass == 1)
FinishDirection();
}
UnfinishedEndpoints<TVectorSize> GetEndpoints(const float channelWeights[TVectorSize]) const
{
MFloat unweightedBase[TVectorSize];
MFloat unweightedOffset[TVectorSize];
for (int ch = 0; ch < TVectorSize; ch++)
{
MFloat min = m_centroid[ch] + m_direction[ch] * m_minDist;
MFloat max = m_centroid[ch] + m_direction[ch] * m_maxDist;
float safeWeight = channelWeights[ch];
if (safeWeight == 0.f)
safeWeight = 1.0f;
unweightedBase[ch] = min / channelWeights[ch];
unweightedOffset[ch] = (max - min) / channelWeights[ch];
}
return UnfinishedEndpoints<TVectorSize>(unweightedBase, unweightedOffset);
}
private:
void ContributeCentroid(const MFloat *value, const MFloat &weight)
{
for (int ch = 0; ch < TVectorSize; ch++)
m_centroid[ch] = m_centroid[ch] + value[ch] * weight;
m_weightTotal = m_weightTotal + weight;
}
void FinishCentroid()
{
MFloat denom = m_weightTotal;
ParallelMath::MakeSafeDenominator(denom);
for (int ch = 0; ch < TVectorSize; ch++)
m_centroid[ch] = m_centroid[ch] / denom;
}
void ContributeDirection(const MFloat *value, const MFloat &weight)
{
MFloat diff[TVectorSize];
for (int ch = 0; ch < TVectorSize; ch++)
diff[ch] = value[ch] - m_centroid[ch];
m_covarianceMatrix.Add(diff, weight);
}
void FinishDirection()
{
MFloat approx[TVectorSize];
for (int ch = 0; ch < TVectorSize; ch++)
approx[ch] = ParallelMath::MakeFloat(1.0f);
for (int i = 0; i < TIterationCount; i++)
{
MFloat product[TVectorSize];
m_covarianceMatrix.Product(product, approx);
MFloat largestComponent = product[0];
for (int ch = 1; ch < TVectorSize; ch++)
largestComponent = ParallelMath::Max(largestComponent, product[ch]);
// product = largestComponent*newApprox
ParallelMath::MakeSafeDenominator(largestComponent);
for (int ch = 0; ch < TVectorSize; ch++)
approx[ch] = product[ch] / largestComponent;
}
// Normalize
MFloat approxLen = ParallelMath::MakeFloatZero();
for (int ch = 0; ch < TVectorSize; ch++)
approxLen = approxLen + approx[ch] * approx[ch];
approxLen = ParallelMath::Sqrt(approxLen);
ParallelMath::MakeSafeDenominator(approxLen);
for (int ch = 0; ch < TVectorSize; ch++)
m_direction[ch] = approx[ch] / approxLen;
}
void ContributeMinMax(const MFloat *value)
{
MFloat dist = ParallelMath::MakeFloatZero();
for (int ch = 0; ch < TVectorSize; ch++)
dist = dist + m_direction[ch] * (value[ch] - m_centroid[ch]);
m_minDist = ParallelMath::Min(m_minDist, dist);
m_maxDist = ParallelMath::Max(m_maxDist, dist);
}
ParallelMath::Float m_centroid[TVectorSize];
ParallelMath::Float m_direction[TVectorSize];
PackedCovarianceMatrix<TVectorSize> m_covarianceMatrix;
ParallelMath::Float m_weightTotal;
ParallelMath::Float m_minDist;
ParallelMath::Float m_maxDist;
};
}
}
#endif

View File

@@ -0,0 +1,282 @@
#pragma once
#include <stdint.h>
// This file is generated by the MakeTables app. Do not edit this file manually.
namespace cvtt { namespace Tables { namespace FakeBT709 {
const uint8_t g_rounding16[] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 4, 4, 4, 4, 4,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 2, 2, 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6,
3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6,
3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7,
3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7,
};
}}}

View File

@@ -0,0 +1,66 @@
/*
Convection Texture Tools
Copyright (c) 2018-2019 Eric Lasota
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.
-------------------------------------------------------------------------------------
Portions based on DirectX Texture Library (DirectXTex)
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
http://go.microsoft.com/fwlink/?LinkId=248926
*/
#include "ConvectionKernels_Config.h"
#if !defined(CVTT_SINGLE_FILE) || defined(CVTT_SINGLE_FILE_IMPL)
#include "ConvectionKernels_IndexSelector.h"
namespace cvtt
{
namespace Internal
{
const ParallelMath::UInt16 g_weightReciprocals[17] =
{
ParallelMath::MakeUInt16(0), // -1
ParallelMath::MakeUInt16(0), // 0
ParallelMath::MakeUInt16(32768), // 1
ParallelMath::MakeUInt16(16384), // 2
ParallelMath::MakeUInt16(10923), // 3
ParallelMath::MakeUInt16(8192), // 4
ParallelMath::MakeUInt16(6554), // 5
ParallelMath::MakeUInt16(5461), // 6
ParallelMath::MakeUInt16(4681), // 7
ParallelMath::MakeUInt16(4096), // 8
ParallelMath::MakeUInt16(3641), // 9
ParallelMath::MakeUInt16(3277), // 10
ParallelMath::MakeUInt16(2979), // 11
ParallelMath::MakeUInt16(2731), // 12
ParallelMath::MakeUInt16(2521), // 13
ParallelMath::MakeUInt16(2341), // 14
ParallelMath::MakeUInt16(2185), // 15
};
}
}
#endif

View File

@@ -0,0 +1,147 @@
#pragma once
#ifndef __CVTT_INDEXSELECTOR_H__
#define __CVTT_INDEXSELECTOR_H__
#include "ConvectionKernels_ParallelMath.h"
namespace cvtt
{
namespace Internal
{
extern const ParallelMath::UInt16 g_weightReciprocals[17];
template<int TVectorSize>
class IndexSelector
{
public:
typedef ParallelMath::Float MFloat;
typedef ParallelMath::UInt16 MUInt16;
typedef ParallelMath::UInt15 MUInt15;
typedef ParallelMath::SInt16 MSInt16;
typedef ParallelMath::AInt16 MAInt16;
typedef ParallelMath::SInt32 MSInt32;
typedef ParallelMath::UInt31 MUInt31;
template<class TInterpolationEPType, class TColorEPType>
void Init(const float *channelWeights, const TInterpolationEPType interpolationEndPoints[2][TVectorSize], const TColorEPType colorSpaceEndpoints[2][TVectorSize], int range)
{
// In BC6H, the interpolation endpoints are higher-precision than the endpoints in color space.
// We need to select indexes using the color-space endpoints.
m_isUniform = true;
for (int ch = 1; ch < TVectorSize; ch++)
{
if (channelWeights[ch] != channelWeights[0])
m_isUniform = false;
}
// To work with channel weights, we need something where:
// pxDiff = px - ep[0]
// epDiff = ep[1] - ep[0]
//
// weightedEPDiff = epDiff * channelWeights
// normalizedWeightedAxis = weightedEPDiff / len(weightedEPDiff)
// normalizedIndex = dot(pxDiff * channelWeights, normalizedWeightedAxis) / len(weightedEPDiff)
// index = normalizedIndex * maxValue
//
// Equivalent to:
// axis = channelWeights * maxValue * epDiff * channelWeights / lenSquared(epDiff * channelWeights)
// index = dot(axis, pxDiff)
for (int ep = 0; ep < 2; ep++)
for (int ch = 0; ch < TVectorSize; ch++)
m_endPoint[ep][ch] = ParallelMath::LosslessCast<MAInt16>::Cast(interpolationEndPoints[ep][ch]);
m_range = range;
m_maxValue = static_cast<float>(range - 1);
MFloat epDiffWeighted[TVectorSize];
for (int ch = 0; ch < TVectorSize; ch++)
{
m_origin[ch] = ParallelMath::ToFloat(colorSpaceEndpoints[0][ch]);
MFloat opposingOriginCh = ParallelMath::ToFloat(colorSpaceEndpoints[1][ch]);
epDiffWeighted[ch] = (opposingOriginCh - m_origin[ch]) * channelWeights[ch];
}
MFloat lenSquared = epDiffWeighted[0] * epDiffWeighted[0];
for (int ch = 1; ch < TVectorSize; ch++)
lenSquared = lenSquared + epDiffWeighted[ch] * epDiffWeighted[ch];
ParallelMath::MakeSafeDenominator(lenSquared);
MFloat maxValueDividedByLengthSquared = ParallelMath::MakeFloat(m_maxValue) / lenSquared;
for (int ch = 0; ch < TVectorSize; ch++)
m_axis[ch] = epDiffWeighted[ch] * channelWeights[ch] * maxValueDividedByLengthSquared;
}
template<bool TSigned>
void Init(const float channelWeights[TVectorSize], const MUInt15 endPoints[2][TVectorSize], int range)
{
MAInt16 converted[2][TVectorSize];
for (int epi = 0; epi < 2; epi++)
for (int ch = 0; ch < TVectorSize; ch++)
converted[epi][ch] = ParallelMath::LosslessCast<MAInt16>::Cast(endPoints[epi][ch]);
Init<MUInt15, MUInt15>(channelWeights, endPoints, endPoints, range);
}
void ReconstructLDR_BC7(const MUInt15 &index, MUInt15* pixel, int numRealChannels)
{
MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 256, 9));
for (int ch = 0; ch < numRealChannels; ch++)
{
MUInt15 ep0f = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::CompactMultiply((ParallelMath::MakeUInt15(64) - weight), ParallelMath::LosslessCast<MUInt15>::Cast(m_endPoint[0][ch])));
MUInt15 ep1f = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::CompactMultiply(weight, ParallelMath::LosslessCast<MUInt15>::Cast(m_endPoint[1][ch])));
pixel[ch] = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ep0f + ep1f + ParallelMath::MakeUInt15(32), 6));
}
}
void ReconstructLDRPrecise(const MUInt15 &index, MUInt15* pixel, int numRealChannels)
{
MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 64, 7));
for (int ch = 0; ch < numRealChannels; ch++)
{
MUInt15 ep0f = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::CompactMultiply((ParallelMath::MakeUInt15(256) - weight), ParallelMath::LosslessCast<MUInt15>::Cast(m_endPoint[0][ch])));
MUInt15 ep1f = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::CompactMultiply(weight, ParallelMath::LosslessCast<MUInt15>::Cast(m_endPoint[1][ch])));
pixel[ch] = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ep0f + ep1f + ParallelMath::MakeUInt15(128), 8));
}
}
void ReconstructLDR_BC7(const MUInt15 &index, MUInt15* pixel)
{
ReconstructLDR_BC7(index, pixel, TVectorSize);
}
void ReconstructLDRPrecise(const MUInt15 &index, MUInt15* pixel)
{
ReconstructLDRPrecise(index, pixel, TVectorSize);
}
MUInt15 SelectIndexLDR(const MFloat* pixel, const ParallelMath::RoundTowardNearestForScope* rtn) const
{
MFloat dist = (pixel[0] - m_origin[0]) * m_axis[0];
for (int ch = 1; ch < TVectorSize; ch++)
dist = dist + (pixel[ch] - m_origin[ch]) * m_axis[ch];
return ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(dist, 0.0f, m_maxValue), rtn);
}
protected:
MAInt16 m_endPoint[2][TVectorSize];
private:
MFloat m_origin[TVectorSize];
MFloat m_axis[TVectorSize];
int m_range;
float m_maxValue;
bool m_isUniform;
};
}
}
#endif

View File

@@ -0,0 +1,155 @@
#pragma once
#ifndef __CVTT_INDEXSELECTORHDR_H__
#define __CVTT_INDEXSELECTORHDR_H__
#include "ConvectionKernels_ParallelMath.h"
#include "ConvectionKernels_IndexSelector.h"
namespace cvtt
{
namespace Internal
{
ParallelMath::SInt16 UnscaleHDRValueSigned(const ParallelMath::SInt16 &v);
ParallelMath::UInt15 UnscaleHDRValueUnsigned(const ParallelMath::UInt16 &v);
template<int TVectorSize>
class IndexSelectorHDR : public IndexSelector<TVectorSize>
{
public:
typedef ParallelMath::UInt15 MUInt15;
typedef ParallelMath::UInt16 MUInt16;
typedef ParallelMath::UInt31 MUInt31;
typedef ParallelMath::SInt16 MSInt16;
typedef ParallelMath::SInt32 MSInt32;
typedef ParallelMath::Float MFloat;
private:
MUInt15 InvertSingle(const MUInt15& anIndex) const
{
MUInt15 inverted = m_maxValueMinusOne - anIndex;
return ParallelMath::Select(m_isInverted, inverted, anIndex);
}
void ReconstructHDRSignedUninverted(const MUInt15 &index, MSInt16* pixel) const
{
MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 256, 9));
for (int ch = 0; ch < TVectorSize; ch++)
{
MSInt16 ep0 = ParallelMath::LosslessCast<MSInt16>::Cast(this->m_endPoint[0][ch]);
MSInt16 ep1 = ParallelMath::LosslessCast<MSInt16>::Cast(this->m_endPoint[1][ch]);
MSInt32 pixel32 = ParallelMath::XMultiply((ParallelMath::MakeUInt15(64) - weight), ep0) + ParallelMath::XMultiply(weight, ep1);
pixel32 = ParallelMath::RightShift(pixel32 + ParallelMath::MakeSInt32(32), 6);
pixel[ch] = UnscaleHDRValueSigned(ParallelMath::ToSInt16(pixel32));
}
}
void ReconstructHDRUnsignedUninverted(const MUInt15 &index, MSInt16* pixel) const
{
MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 256, 9));
for (int ch = 0; ch < TVectorSize; ch++)
{
MUInt16 ep0 = ParallelMath::LosslessCast<MUInt16>::Cast(this->m_endPoint[0][ch]);
MUInt16 ep1 = ParallelMath::LosslessCast<MUInt16>::Cast(this->m_endPoint[1][ch]);
MUInt31 pixel31 = ParallelMath::XMultiply((ParallelMath::MakeUInt15(64) - weight), ep0) + ParallelMath::XMultiply(weight, ep1);
pixel31 = ParallelMath::RightShift(pixel31 + ParallelMath::MakeUInt31(32), 6);
pixel[ch] = ParallelMath::LosslessCast<MSInt16>::Cast(UnscaleHDRValueUnsigned(ParallelMath::ToUInt16(pixel31)));
}
}
MFloat ErrorForInterpolatorComponent(int index, int ch, const MFloat *pixel) const
{
MFloat diff = pixel[ch] - m_reconstructedInterpolators[index][ch];
return diff * diff;
}
MFloat ErrorForInterpolator(int index, const MFloat *pixel) const
{
MFloat error = ErrorForInterpolatorComponent(index, 0, pixel);
for (int ch = 1; ch < TVectorSize; ch++)
error = error + ErrorForInterpolatorComponent(index, ch, pixel);
return error;
}
public:
void InitHDR(int range, bool isSigned, bool fastIndexing, const float *channelWeights)
{
assert(range <= 16);
m_range = range;
m_isInverted = ParallelMath::MakeBoolInt16(false);
m_maxValueMinusOne = ParallelMath::MakeUInt15(static_cast<uint16_t>(range - 1));
if (!fastIndexing)
{
for (int i = 0; i < range; i++)
{
MSInt16 recon2CL[TVectorSize];
if (isSigned)
ReconstructHDRSignedUninverted(ParallelMath::MakeUInt15(static_cast<uint16_t>(i)), recon2CL);
else
ReconstructHDRUnsignedUninverted(ParallelMath::MakeUInt15(static_cast<uint16_t>(i)), recon2CL);
for (int ch = 0; ch < TVectorSize; ch++)
m_reconstructedInterpolators[i][ch] = ParallelMath::TwosCLHalfToFloat(recon2CL[ch]) * channelWeights[ch];
}
}
}
void ReconstructHDRSigned(const MUInt15 &index, MSInt16* pixel) const
{
ReconstructHDRSignedUninverted(InvertSingle(index), pixel);
}
void ReconstructHDRUnsigned(const MUInt15 &index, MSInt16* pixel) const
{
ReconstructHDRUnsignedUninverted(InvertSingle(index), pixel);
}
void ConditionalInvert(const ParallelMath::Int16CompFlag &invert)
{
m_isInverted = invert;
}
MUInt15 SelectIndexHDRSlow(const MFloat* pixel, const ParallelMath::RoundTowardNearestForScope*) const
{
MUInt15 index = ParallelMath::MakeUInt15(0);
MFloat bestError = ErrorForInterpolator(0, pixel);
for (int i = 1; i < m_range; i++)
{
MFloat error = ErrorForInterpolator(i, pixel);
ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(error, bestError);
ParallelMath::ConditionalSet(index, ParallelMath::FloatFlagToInt16(errorBetter), ParallelMath::MakeUInt15(static_cast<uint16_t>(i)));
bestError = ParallelMath::Min(bestError, error);
}
return InvertSingle(index);
}
MUInt15 SelectIndexHDRFast(const MFloat* pixel, const ParallelMath::RoundTowardNearestForScope* rtn) const
{
return InvertSingle(this->SelectIndexLDR(pixel, rtn));
}
private:
MFloat m_reconstructedInterpolators[16][TVectorSize];
ParallelMath::Int16CompFlag m_isInverted;
MUInt15 m_maxValueMinusOne;
int m_range;
};
}
}
#endif

View File

@@ -0,0 +1,68 @@
#pragma once
#ifndef __CVTT_COVARIANCEMATRIX_H__
#define __CVTT_COVARIANCEMATRIX_H__
namespace cvtt
{
namespace Internal
{
template<int TMatrixSize>
class PackedCovarianceMatrix
{
public:
// 0: xx,
// 1: xy, yy
// 3: xz, yz, zz
// 6: xw, yw, zw, ww
// ... etc.
static const int PyramidSize = (TMatrixSize * (TMatrixSize + 1)) / 2;
typedef ParallelMath::Float MFloat;
PackedCovarianceMatrix()
{
for (int i = 0; i < PyramidSize; i++)
m_values[i] = ParallelMath::MakeFloatZero();
}
void Add(const ParallelMath::Float *vec, const ParallelMath::Float &weight)
{
int index = 0;
for (int row = 0; row < TMatrixSize; row++)
{
for (int col = 0; col <= row; col++)
{
m_values[index] = m_values[index] + vec[row] * vec[col] * weight;
index++;
}
}
}
void Product(MFloat *outVec, const MFloat *inVec)
{
for (int row = 0; row < TMatrixSize; row++)
{
MFloat sum = ParallelMath::MakeFloatZero();
int index = (row * (row + 1)) >> 1;
for (int col = 0; col < TMatrixSize; col++)
{
sum = sum + inVec[col] * m_values[index];
if (col >= row)
index += col + 1;
else
index++;
}
outVec[row] = sum;
}
}
private:
ParallelMath::Float m_values[PyramidSize];
};
}
}
#endif

File diff suppressed because it is too large Load Diff

1054
thirdparty/cvtt/ConvectionKernels_S3TC.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
#pragma once
#ifndef __CVTT_S3TC_H__
#define __CVTT_S3TC_H__
#include "ConvectionKernels_ParallelMath.h"
namespace cvtt
{
namespace Internal
{
template<int TVectorSize>
class EndpointRefiner;
}
struct PixelBlockU8;
}
namespace cvtt
{
namespace Internal
{
class S3TCComputer
{
public:
typedef ParallelMath::Float MFloat;
typedef ParallelMath::SInt16 MSInt16;
typedef ParallelMath::UInt15 MUInt15;
typedef ParallelMath::UInt16 MUInt16;
typedef ParallelMath::SInt32 MSInt32;
static void Init(MFloat& error);
static void QuantizeTo6Bits(MUInt15& v);
static void QuantizeTo5Bits(MUInt15& v);
static void QuantizeTo565(MUInt15 endPoint[3]);
static MFloat ParanoidFactorForSpan(const MSInt16& span);
static MFloat ParanoidDiff(const MUInt15& a, const MUInt15& b, const MFloat& d);
static void TestSingleColor(uint32_t flags, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], int range, const float* channelWeights,
MFloat &bestError, MUInt15 bestEndpoints[2][3], MUInt15 bestIndexes[16], MUInt15 &bestRange, const ParallelMath::RoundTowardNearestForScope *rtn);
static void TestEndpoints(uint32_t flags, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], const MFloat preWeightedPixels[16][4], const MUInt15 unquantizedEndPoints[2][3], int range, const float* channelWeights,
MFloat &bestError, MUInt15 bestEndpoints[2][3], MUInt15 bestIndexes[16], MUInt15 &bestRange, EndpointRefiner<3> *refiner, const ParallelMath::RoundTowardNearestForScope *rtn);
static void TestCounts(uint32_t flags, const int *counts, int nCounts, const MUInt15 &numElements, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], const MFloat preWeightedPixels[16][4], bool alphaTest,
const MFloat floatSortedInputs[16][4], const MFloat preWeightedFloatSortedInputs[16][4], const float *channelWeights, MFloat &bestError, MUInt15 bestEndpoints[2][3], MUInt15 bestIndexes[16], MUInt15 &bestRange,
const ParallelMath::RoundTowardNearestForScope* rtn);
static void PackExplicitAlpha(uint32_t flags, const PixelBlockU8* inputs, int inputChannel, uint8_t* packedBlocks, size_t packedBlockStride);
static void PackInterpolatedAlpha(uint32_t flags, const PixelBlockU8* inputs, int inputChannel, uint8_t* packedBlocks, size_t packedBlockStride, bool isSigned, int maxTweakRounds, int numRefineRounds);
static void PackRGB(uint32_t flags, const PixelBlockU8* inputs, uint8_t* packedBlocks, size_t packedBlockStride, const float channelWeights[4], bool alphaTest, float alphaThreshold, bool exhaustive, int maxTweakRounds, int numRefineRounds);
};
}
}
#endif

View File

@@ -0,0 +1,304 @@
#pragma once
#include <stdint.h>
// This file is generated by the MakeTables app. Do not edit this file manually.
namespace cvtt { namespace Tables { namespace S3TCSC {
struct TableEntry
{
uint8_t m_min;
uint8_t m_max;
uint8_t m_actualColor;
uint8_t m_span;
};
TableEntry g_singleColor5_3[256] =
{
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 8, 2, 8 }, { 0, 8, 2, 8 }, { 8, 0, 5, 8 }, { 8, 0, 5, 8 }, { 8, 0, 5, 8 }, { 8, 8, 8, 0 },
{ 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 16, 10, 8 }, { 0, 33, 11, 33 }, { 16, 8, 13, 8 }, { 16, 8, 13, 8 }, { 16, 8, 13, 8 }, { 16, 16, 16, 0 },
{ 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 24, 18, 8 }, { 8, 41, 19, 33 }, { 24, 16, 21, 8 }, { 24, 16, 21, 8 }, { 33, 0, 22, 33 }, { 24, 24, 24, 0 },
{ 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 33, 27, 9 }, { 24, 33, 27, 9 }, { 24, 33, 27, 9 }, { 24, 41, 29, 17 }, { 33, 24, 30, 9 }, { 33, 24, 30, 9 },
{ 24, 49, 32, 25 }, { 33, 33, 33, 0 }, { 33, 33, 33, 0 }, { 33, 41, 35, 8 }, { 33, 41, 35, 8 }, { 41, 33, 38, 8 }, { 41, 33, 38, 8 }, { 41, 33, 38, 8 },
{ 49, 24, 40, 25 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 41, 49, 43, 8 }, { 33, 66, 44, 33 }, { 49, 41, 46, 8 }, { 49, 41, 46, 8 }, { 49, 41, 46, 8 },
{ 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 57, 51, 8 }, { 41, 74, 52, 33 }, { 57, 49, 54, 8 }, { 57, 49, 54, 8 }, { 66, 33, 55, 33 },
{ 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 66, 60, 9 }, { 57, 66, 60, 9 }, { 57, 66, 60, 9 }, { 57, 74, 62, 17 }, { 66, 57, 63, 9 },
{ 66, 57, 63, 9 }, { 57, 82, 65, 25 }, { 66, 66, 66, 0 }, { 66, 66, 66, 0 }, { 66, 74, 68, 8 }, { 66, 74, 68, 8 }, { 74, 66, 71, 8 }, { 74, 66, 71, 8 },
{ 74, 66, 71, 8 }, { 82, 57, 73, 25 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 74, 82, 76, 8 }, { 66, 99, 77, 33 }, { 82, 74, 79, 8 }, { 82, 74, 79, 8 },
{ 82, 74, 79, 8 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 90, 84, 8 }, { 74, 107, 85, 33 }, { 90, 82, 87, 8 }, { 90, 82, 87, 8 },
{ 99, 66, 88, 33 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 99, 93, 9 }, { 90, 99, 93, 9 }, { 90, 99, 93, 9 }, { 90, 107, 95, 17 },
{ 99, 90, 96, 9 }, { 99, 90, 96, 9 }, { 90, 115, 98, 25 }, { 99, 99, 99, 0 }, { 99, 99, 99, 0 }, { 99, 107, 101, 8 }, { 99, 107, 101, 8 }, { 107, 99, 104, 8 },
{ 107, 99, 104, 8 }, { 107, 99, 104, 8 }, { 115, 90, 106, 25 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 107, 115, 109, 8 }, { 99, 132, 110, 33 }, { 115, 107, 112, 8 },
{ 115, 107, 112, 8 }, { 115, 107, 112, 8 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 123, 117, 8 }, { 107, 140, 118, 33 }, { 123, 115, 120, 8 },
{ 123, 115, 120, 8 }, { 132, 99, 121, 33 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 132, 126, 9 }, { 123, 132, 126, 9 }, { 123, 132, 126, 9 },
{ 123, 140, 128, 17 }, { 132, 123, 129, 9 }, { 132, 123, 129, 9 }, { 123, 148, 131, 25 }, { 132, 132, 132, 0 }, { 132, 132, 132, 0 }, { 132, 140, 134, 8 }, { 132, 140, 134, 8 },
{ 140, 132, 137, 8 }, { 140, 132, 137, 8 }, { 140, 132, 137, 8 }, { 148, 123, 139, 25 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 140, 148, 142, 8 }, { 132, 165, 143, 33 },
{ 148, 140, 145, 8 }, { 148, 140, 145, 8 }, { 148, 140, 145, 8 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 156, 150, 8 }, { 140, 173, 151, 33 },
{ 156, 148, 153, 8 }, { 156, 148, 153, 8 }, { 165, 132, 154, 33 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 165, 159, 9 }, { 156, 165, 159, 9 },
{ 156, 165, 159, 9 }, { 156, 173, 161, 17 }, { 165, 156, 162, 9 }, { 165, 156, 162, 9 }, { 156, 181, 164, 25 }, { 165, 165, 165, 0 }, { 165, 165, 165, 0 }, { 165, 173, 167, 8 },
{ 165, 173, 167, 8 }, { 173, 165, 170, 8 }, { 173, 165, 170, 8 }, { 173, 165, 170, 8 }, { 181, 156, 172, 25 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, { 173, 181, 175, 8 },
{ 165, 198, 176, 33 }, { 181, 173, 178, 8 }, { 181, 173, 178, 8 }, { 181, 173, 178, 8 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 189, 183, 8 },
{ 173, 206, 184, 33 }, { 189, 181, 186, 8 }, { 189, 181, 186, 8 }, { 198, 165, 187, 33 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 198, 192, 9 },
{ 189, 198, 192, 9 }, { 189, 198, 192, 9 }, { 189, 206, 194, 17 }, { 198, 189, 195, 9 }, { 198, 189, 195, 9 }, { 189, 214, 197, 25 }, { 198, 198, 198, 0 }, { 198, 198, 198, 0 },
{ 198, 206, 200, 8 }, { 198, 206, 200, 8 }, { 206, 198, 203, 8 }, { 206, 198, 203, 8 }, { 206, 198, 203, 8 }, { 214, 189, 205, 25 }, { 206, 206, 206, 0 }, { 206, 206, 206, 0 },
{ 206, 214, 208, 8 }, { 198, 231, 209, 33 }, { 214, 206, 211, 8 }, { 214, 206, 211, 8 }, { 214, 206, 211, 8 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 },
{ 214, 222, 216, 8 }, { 206, 239, 217, 33 }, { 222, 214, 219, 8 }, { 222, 214, 219, 8 }, { 231, 198, 220, 33 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 },
{ 222, 231, 225, 9 }, { 222, 231, 225, 9 }, { 222, 231, 225, 9 }, { 222, 239, 227, 17 }, { 231, 222, 228, 9 }, { 231, 222, 228, 9 }, { 222, 247, 230, 25 }, { 231, 231, 231, 0 },
{ 231, 231, 231, 0 }, { 231, 239, 233, 8 }, { 231, 239, 233, 8 }, { 239, 231, 236, 8 }, { 239, 231, 236, 8 }, { 239, 231, 236, 8 }, { 247, 222, 238, 25 }, { 239, 239, 239, 0 },
{ 239, 239, 239, 0 }, { 239, 247, 241, 8 }, { 239, 247, 241, 8 }, { 247, 239, 244, 8 }, { 247, 239, 244, 8 }, { 247, 239, 244, 8 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 },
{ 247, 247, 247, 0 }, { 247, 255, 249, 8 }, { 247, 255, 249, 8 }, { 255, 247, 252, 8 }, { 255, 247, 252, 8 }, { 255, 247, 252, 8 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 },
};
TableEntry g_singleColor6_3[256] =
{
{ 0, 0, 0, 0 }, { 0, 4, 1, 4 }, { 4, 0, 2, 4 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 4, 8, 5, 4 }, { 8, 4, 6, 4 }, { 8, 8, 8, 0 },
{ 8, 8, 8, 0 }, { 8, 12, 9, 4 }, { 12, 8, 10, 4 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 12, 16, 13, 4 }, { 16, 12, 14, 4 }, { 16, 16, 16, 0 },
{ 16, 16, 16, 0 }, { 16, 20, 17, 4 }, { 20, 16, 18, 4 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 20, 24, 21, 4 }, { 24, 20, 22, 4 }, { 0, 69, 23, 69 },
{ 24, 24, 24, 0 }, { 24, 28, 25, 4 }, { 28, 24, 26, 4 }, { 8, 65, 27, 57 }, { 28, 28, 28, 0 }, { 28, 32, 29, 4 }, { 32, 28, 30, 4 }, { 12, 69, 31, 57 },
{ 32, 32, 32, 0 }, { 32, 36, 33, 4 }, { 36, 32, 34, 4 }, { 20, 65, 35, 45 }, { 36, 36, 36, 0 }, { 36, 40, 37, 4 }, { 40, 36, 38, 4 }, { 24, 69, 39, 45 },
{ 40, 40, 40, 0 }, { 40, 44, 41, 4 }, { 44, 40, 42, 4 }, { 32, 65, 43, 33 }, { 44, 44, 44, 0 }, { 44, 48, 45, 4 }, { 48, 44, 46, 4 }, { 36, 69, 47, 33 },
{ 48, 48, 48, 0 }, { 48, 52, 49, 4 }, { 52, 48, 50, 4 }, { 44, 65, 51, 21 }, { 52, 52, 52, 0 }, { 52, 56, 53, 4 }, { 56, 52, 54, 4 }, { 48, 69, 55, 21 },
{ 56, 56, 56, 0 }, { 56, 60, 57, 4 }, { 60, 56, 58, 4 }, { 56, 65, 59, 9 }, { 60, 60, 60, 0 }, { 60, 65, 61, 5 }, { 65, 56, 62, 9 }, { 65, 60, 63, 5 },
{ 60, 73, 64, 13 }, { 65, 65, 65, 0 }, { 65, 69, 66, 4 }, { 69, 65, 67, 4 }, { 73, 60, 68, 13 }, { 69, 69, 69, 0 }, { 69, 73, 70, 4 }, { 73, 69, 71, 4 },
{ 81, 56, 72, 25 }, { 73, 73, 73, 0 }, { 73, 77, 74, 4 }, { 77, 73, 75, 4 }, { 85, 60, 76, 25 }, { 77, 77, 77, 0 }, { 77, 81, 78, 4 }, { 81, 77, 79, 4 },
{ 93, 56, 80, 37 }, { 81, 81, 81, 0 }, { 81, 85, 82, 4 }, { 85, 81, 83, 4 }, { 97, 60, 84, 37 }, { 85, 85, 85, 0 }, { 85, 89, 86, 4 }, { 89, 85, 87, 4 },
{ 105, 56, 88, 49 }, { 89, 89, 89, 0 }, { 89, 93, 90, 4 }, { 93, 89, 91, 4 }, { 109, 60, 92, 49 }, { 93, 93, 93, 0 }, { 93, 97, 94, 4 }, { 97, 93, 95, 4 },
{ 77, 134, 96, 57 }, { 97, 97, 97, 0 }, { 97, 101, 98, 4 }, { 101, 97, 99, 4 }, { 85, 130, 100, 45 }, { 101, 101, 101, 0 }, { 101, 105, 102, 4 }, { 105, 101, 103, 4 },
{ 89, 134, 104, 45 }, { 105, 105, 105, 0 }, { 105, 109, 106, 4 }, { 109, 105, 107, 4 }, { 97, 130, 108, 33 }, { 109, 109, 109, 0 }, { 109, 113, 110, 4 }, { 113, 109, 111, 4 },
{ 101, 134, 112, 33 }, { 113, 113, 113, 0 }, { 113, 117, 114, 4 }, { 117, 113, 115, 4 }, { 109, 130, 116, 21 }, { 117, 117, 117, 0 }, { 117, 121, 118, 4 }, { 121, 117, 119, 4 },
{ 113, 134, 120, 21 }, { 121, 121, 121, 0 }, { 121, 125, 122, 4 }, { 125, 121, 123, 4 }, { 121, 130, 124, 9 }, { 125, 125, 125, 0 }, { 125, 130, 126, 5 }, { 130, 121, 127, 9 },
{ 130, 125, 128, 5 }, { 125, 138, 129, 13 }, { 130, 130, 130, 0 }, { 130, 134, 131, 4 }, { 134, 130, 132, 4 }, { 138, 125, 133, 13 }, { 134, 134, 134, 0 }, { 134, 138, 135, 4 },
{ 138, 134, 136, 4 }, { 146, 121, 137, 25 }, { 138, 138, 138, 0 }, { 138, 142, 139, 4 }, { 142, 138, 140, 4 }, { 150, 125, 141, 25 }, { 142, 142, 142, 0 }, { 142, 146, 143, 4 },
{ 146, 142, 144, 4 }, { 158, 121, 145, 37 }, { 146, 146, 146, 0 }, { 146, 150, 147, 4 }, { 150, 146, 148, 4 }, { 162, 125, 149, 37 }, { 150, 150, 150, 0 }, { 150, 154, 151, 4 },
{ 154, 150, 152, 4 }, { 170, 121, 153, 49 }, { 154, 154, 154, 0 }, { 154, 158, 155, 4 }, { 158, 154, 156, 4 }, { 174, 125, 157, 49 }, { 158, 158, 158, 0 }, { 158, 162, 159, 4 },
{ 162, 158, 160, 4 }, { 142, 199, 161, 57 }, { 162, 162, 162, 0 }, { 162, 166, 163, 4 }, { 166, 162, 164, 4 }, { 150, 195, 165, 45 }, { 166, 166, 166, 0 }, { 166, 170, 167, 4 },
{ 170, 166, 168, 4 }, { 154, 199, 169, 45 }, { 170, 170, 170, 0 }, { 170, 174, 171, 4 }, { 174, 170, 172, 4 }, { 162, 195, 173, 33 }, { 174, 174, 174, 0 }, { 174, 178, 175, 4 },
{ 178, 174, 176, 4 }, { 166, 199, 177, 33 }, { 178, 178, 178, 0 }, { 178, 182, 179, 4 }, { 182, 178, 180, 4 }, { 174, 195, 181, 21 }, { 182, 182, 182, 0 }, { 182, 186, 183, 4 },
{ 186, 182, 184, 4 }, { 178, 199, 185, 21 }, { 186, 186, 186, 0 }, { 186, 190, 187, 4 }, { 190, 186, 188, 4 }, { 186, 195, 189, 9 }, { 190, 190, 190, 0 }, { 190, 195, 191, 5 },
{ 195, 186, 192, 9 }, { 195, 190, 193, 5 }, { 190, 203, 194, 13 }, { 195, 195, 195, 0 }, { 195, 199, 196, 4 }, { 199, 195, 197, 4 }, { 203, 190, 198, 13 }, { 199, 199, 199, 0 },
{ 199, 203, 200, 4 }, { 203, 199, 201, 4 }, { 211, 186, 202, 25 }, { 203, 203, 203, 0 }, { 203, 207, 204, 4 }, { 207, 203, 205, 4 }, { 215, 190, 206, 25 }, { 207, 207, 207, 0 },
{ 207, 211, 208, 4 }, { 211, 207, 209, 4 }, { 223, 186, 210, 37 }, { 211, 211, 211, 0 }, { 211, 215, 212, 4 }, { 215, 211, 213, 4 }, { 227, 190, 214, 37 }, { 215, 215, 215, 0 },
{ 215, 219, 216, 4 }, { 219, 215, 217, 4 }, { 235, 186, 218, 49 }, { 219, 219, 219, 0 }, { 219, 223, 220, 4 }, { 223, 219, 221, 4 }, { 239, 190, 222, 49 }, { 223, 223, 223, 0 },
{ 223, 227, 224, 4 }, { 227, 223, 225, 4 }, { 247, 186, 226, 61 }, { 227, 227, 227, 0 }, { 227, 231, 228, 4 }, { 231, 227, 229, 4 }, { 251, 190, 230, 61 }, { 231, 231, 231, 0 },
{ 231, 235, 232, 4 }, { 235, 231, 233, 4 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 235, 239, 236, 4 }, { 239, 235, 237, 4 }, { 239, 239, 239, 0 }, { 239, 239, 239, 0 },
{ 239, 243, 240, 4 }, { 243, 239, 241, 4 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 243, 247, 244, 4 }, { 247, 243, 245, 4 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 },
{ 247, 251, 248, 4 }, { 251, 247, 249, 4 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 251, 255, 252, 4 }, { 255, 251, 253, 4 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 },
};
TableEntry g_singleColor5_2[256] =
{
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 8, 4, 8 }, { 0, 8, 4, 8 }, { 0, 8, 4, 8 }, { 8, 8, 8, 0 }, { 8, 8, 8, 0 },
{ 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 16, 12, 8 }, { 8, 16, 12, 8 }, { 8, 16, 12, 8 }, { 16, 16, 16, 0 }, { 16, 16, 16, 0 },
{ 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 24, 20, 8 }, { 16, 24, 20, 8 }, { 16, 24, 20, 8 }, { 24, 24, 24, 0 }, { 24, 24, 24, 0 },
{ 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 41, 32, 17 },
{ 24, 41, 32, 17 }, { 33, 33, 33, 0 }, { 33, 33, 33, 0 }, { 24, 49, 36, 25 }, { 24, 49, 36, 25 }, { 33, 41, 37, 8 }, { 33, 41, 37, 8 }, { 24, 57, 40, 33 },
{ 24, 57, 40, 33 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 41, 49, 45, 8 }, { 41, 49, 45, 8 }, { 41, 49, 45, 8 }, { 49, 49, 49, 0 },
{ 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 57, 53, 8 }, { 49, 57, 53, 8 }, { 49, 57, 53, 8 }, { 57, 57, 57, 0 },
{ 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 },
{ 57, 74, 65, 17 }, { 57, 74, 65, 17 }, { 66, 66, 66, 0 }, { 66, 66, 66, 0 }, { 57, 82, 69, 25 }, { 57, 82, 69, 25 }, { 66, 74, 70, 8 }, { 66, 74, 70, 8 },
{ 57, 90, 73, 33 }, { 57, 90, 73, 33 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 74, 82, 78, 8 }, { 74, 82, 78, 8 }, { 74, 82, 78, 8 },
{ 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 90, 86, 8 }, { 82, 90, 86, 8 }, { 82, 90, 86, 8 },
{ 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 99, 94, 9 }, { 90, 99, 94, 9 }, { 90, 99, 94, 9 },
{ 90, 99, 94, 9 }, { 90, 107, 98, 17 }, { 90, 107, 98, 17 }, { 99, 99, 99, 0 }, { 99, 99, 99, 0 }, { 90, 115, 102, 25 }, { 90, 115, 102, 25 }, { 99, 107, 103, 8 },
{ 99, 107, 103, 8 }, { 90, 123, 106, 33 }, { 90, 123, 106, 33 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 107, 115, 111, 8 }, { 107, 115, 111, 8 },
{ 107, 115, 111, 8 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 123, 119, 8 }, { 115, 123, 119, 8 },
{ 115, 123, 119, 8 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 132, 127, 9 }, { 123, 132, 127, 9 },
{ 123, 132, 127, 9 }, { 123, 132, 127, 9 }, { 123, 140, 131, 17 }, { 123, 140, 131, 17 }, { 132, 132, 132, 0 }, { 132, 132, 132, 0 }, { 123, 148, 135, 25 }, { 123, 148, 135, 25 },
{ 132, 140, 136, 8 }, { 132, 140, 136, 8 }, { 123, 156, 139, 33 }, { 123, 156, 139, 33 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 140, 148, 144, 8 },
{ 140, 148, 144, 8 }, { 140, 148, 144, 8 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 156, 152, 8 },
{ 148, 156, 152, 8 }, { 148, 156, 152, 8 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 165, 160, 9 },
{ 156, 165, 160, 9 }, { 156, 165, 160, 9 }, { 156, 165, 160, 9 }, { 156, 173, 164, 17 }, { 156, 173, 164, 17 }, { 165, 165, 165, 0 }, { 165, 165, 165, 0 }, { 156, 181, 168, 25 },
{ 156, 181, 168, 25 }, { 165, 173, 169, 8 }, { 165, 173, 169, 8 }, { 156, 189, 172, 33 }, { 156, 189, 172, 33 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 },
{ 173, 181, 177, 8 }, { 173, 181, 177, 8 }, { 173, 181, 177, 8 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 },
{ 181, 189, 185, 8 }, { 181, 189, 185, 8 }, { 181, 189, 185, 8 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 },
{ 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 206, 197, 17 }, { 189, 206, 197, 17 }, { 198, 198, 198, 0 }, { 198, 198, 198, 0 },
{ 189, 214, 201, 25 }, { 189, 214, 201, 25 }, { 198, 206, 202, 8 }, { 198, 206, 202, 8 }, { 189, 222, 205, 33 }, { 189, 222, 205, 33 }, { 206, 206, 206, 0 }, { 206, 206, 206, 0 },
{ 206, 206, 206, 0 }, { 206, 214, 210, 8 }, { 206, 214, 210, 8 }, { 206, 214, 210, 8 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 },
{ 214, 214, 214, 0 }, { 214, 222, 218, 8 }, { 214, 222, 218, 8 }, { 214, 222, 218, 8 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 },
{ 222, 222, 222, 0 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 239, 230, 17 }, { 222, 239, 230, 17 }, { 231, 231, 231, 0 },
{ 231, 231, 231, 0 }, { 222, 247, 234, 25 }, { 222, 247, 234, 25 }, { 231, 239, 235, 8 }, { 231, 239, 235, 8 }, { 222, 255, 238, 33 }, { 222, 255, 238, 33 }, { 239, 239, 239, 0 },
{ 239, 239, 239, 0 }, { 239, 239, 239, 0 }, { 239, 247, 243, 8 }, { 239, 247, 243, 8 }, { 239, 247, 243, 8 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 },
{ 247, 247, 247, 0 }, { 247, 247, 247, 0 }, { 247, 255, 251, 8 }, { 247, 255, 251, 8 }, { 247, 255, 251, 8 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 },
};
TableEntry g_singleColor6_2[256] =
{
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 4, 2, 4 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 4, 8, 6, 4 }, { 8, 8, 8, 0 },
{ 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 12, 10, 4 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 12, 16, 14, 4 }, { 16, 16, 16, 0 },
{ 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 20, 18, 4 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 20, 24, 22, 4 }, { 24, 24, 24, 0 },
{ 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 28, 26, 4 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 28, 32, 30, 4 }, { 32, 32, 32, 0 },
{ 32, 32, 32, 0 }, { 32, 32, 32, 0 }, { 32, 36, 34, 4 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 36, 40, 38, 4 }, { 40, 40, 40, 0 },
{ 40, 40, 40, 0 }, { 40, 40, 40, 0 }, { 40, 44, 42, 4 }, { 44, 44, 44, 0 }, { 44, 44, 44, 0 }, { 44, 44, 44, 0 }, { 44, 48, 46, 4 }, { 48, 48, 48, 0 },
{ 48, 48, 48, 0 }, { 48, 48, 48, 0 }, { 48, 52, 50, 4 }, { 52, 52, 52, 0 }, { 52, 52, 52, 0 }, { 52, 52, 52, 0 }, { 52, 56, 54, 4 }, { 56, 56, 56, 0 },
{ 56, 56, 56, 0 }, { 56, 56, 56, 0 }, { 56, 60, 58, 4 }, { 60, 60, 60, 0 }, { 60, 60, 60, 0 }, { 60, 60, 60, 0 }, { 60, 65, 62, 5 }, { 60, 65, 62, 5 },
{ 60, 69, 64, 9 }, { 65, 65, 65, 0 }, { 60, 73, 66, 13 }, { 65, 69, 67, 4 }, { 60, 77, 68, 17 }, { 69, 69, 69, 0 }, { 60, 81, 70, 21 }, { 69, 73, 71, 4 },
{ 60, 85, 72, 25 }, { 73, 73, 73, 0 }, { 60, 89, 74, 29 }, { 73, 77, 75, 4 }, { 60, 93, 76, 33 }, { 77, 77, 77, 0 }, { 60, 97, 78, 37 }, { 77, 81, 79, 4 },
{ 60, 101, 80, 41 }, { 81, 81, 81, 0 }, { 60, 105, 82, 45 }, { 81, 85, 83, 4 }, { 60, 109, 84, 49 }, { 85, 85, 85, 0 }, { 60, 113, 86, 53 }, { 85, 89, 87, 4 },
{ 60, 117, 88, 57 }, { 89, 89, 89, 0 }, { 60, 121, 90, 61 }, { 89, 93, 91, 4 }, { 60, 125, 92, 65 }, { 93, 93, 93, 0 }, { 93, 93, 93, 0 }, { 93, 97, 95, 4 },
{ 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 97, 101, 99, 4 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 101, 105, 103, 4 },
{ 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 105, 109, 107, 4 }, { 109, 109, 109, 0 }, { 109, 109, 109, 0 }, { 109, 109, 109, 0 }, { 109, 113, 111, 4 },
{ 113, 113, 113, 0 }, { 113, 113, 113, 0 }, { 113, 113, 113, 0 }, { 113, 117, 115, 4 }, { 117, 117, 117, 0 }, { 117, 117, 117, 0 }, { 117, 117, 117, 0 }, { 117, 121, 119, 4 },
{ 121, 121, 121, 0 }, { 121, 121, 121, 0 }, { 121, 121, 121, 0 }, { 121, 125, 123, 4 }, { 125, 125, 125, 0 }, { 125, 125, 125, 0 }, { 125, 125, 125, 0 }, { 125, 130, 127, 5 },
{ 125, 130, 127, 5 }, { 125, 134, 129, 9 }, { 130, 130, 130, 0 }, { 125, 138, 131, 13 }, { 130, 134, 132, 4 }, { 125, 142, 133, 17 }, { 134, 134, 134, 0 }, { 125, 146, 135, 21 },
{ 134, 138, 136, 4 }, { 125, 150, 137, 25 }, { 138, 138, 138, 0 }, { 125, 154, 139, 29 }, { 138, 142, 140, 4 }, { 125, 158, 141, 33 }, { 142, 142, 142, 0 }, { 125, 162, 143, 37 },
{ 142, 146, 144, 4 }, { 125, 166, 145, 41 }, { 146, 146, 146, 0 }, { 125, 170, 147, 45 }, { 146, 150, 148, 4 }, { 125, 174, 149, 49 }, { 150, 150, 150, 0 }, { 125, 178, 151, 53 },
{ 150, 154, 152, 4 }, { 125, 182, 153, 57 }, { 154, 154, 154, 0 }, { 125, 186, 155, 61 }, { 154, 158, 156, 4 }, { 125, 190, 157, 65 }, { 158, 158, 158, 0 }, { 158, 158, 158, 0 },
{ 158, 162, 160, 4 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 162, 166, 164, 4 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 },
{ 166, 170, 168, 4 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 170, 174, 172, 4 }, { 174, 174, 174, 0 }, { 174, 174, 174, 0 }, { 174, 174, 174, 0 },
{ 174, 178, 176, 4 }, { 178, 178, 178, 0 }, { 178, 178, 178, 0 }, { 178, 178, 178, 0 }, { 178, 182, 180, 4 }, { 182, 182, 182, 0 }, { 182, 182, 182, 0 }, { 182, 182, 182, 0 },
{ 182, 186, 184, 4 }, { 186, 186, 186, 0 }, { 186, 186, 186, 0 }, { 186, 186, 186, 0 }, { 186, 190, 188, 4 }, { 190, 190, 190, 0 }, { 190, 190, 190, 0 }, { 190, 190, 190, 0 },
{ 190, 195, 192, 5 }, { 190, 195, 192, 5 }, { 190, 199, 194, 9 }, { 195, 195, 195, 0 }, { 190, 203, 196, 13 }, { 195, 199, 197, 4 }, { 190, 207, 198, 17 }, { 199, 199, 199, 0 },
{ 190, 211, 200, 21 }, { 199, 203, 201, 4 }, { 190, 215, 202, 25 }, { 203, 203, 203, 0 }, { 190, 219, 204, 29 }, { 203, 207, 205, 4 }, { 190, 223, 206, 33 }, { 207, 207, 207, 0 },
{ 190, 227, 208, 37 }, { 207, 211, 209, 4 }, { 190, 231, 210, 41 }, { 211, 211, 211, 0 }, { 190, 235, 212, 45 }, { 211, 215, 213, 4 }, { 190, 239, 214, 49 }, { 215, 215, 215, 0 },
{ 190, 243, 216, 53 }, { 215, 219, 217, 4 }, { 190, 247, 218, 57 }, { 219, 219, 219, 0 }, { 190, 251, 220, 61 }, { 219, 223, 221, 4 }, { 190, 255, 222, 65 }, { 223, 223, 223, 0 },
{ 223, 223, 223, 0 }, { 223, 227, 225, 4 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 227, 231, 229, 4 }, { 231, 231, 231, 0 }, { 231, 231, 231, 0 },
{ 231, 231, 231, 0 }, { 231, 235, 233, 4 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 235, 239, 237, 4 }, { 239, 239, 239, 0 }, { 239, 239, 239, 0 },
{ 239, 239, 239, 0 }, { 239, 243, 241, 4 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 243, 247, 245, 4 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 },
{ 247, 247, 247, 0 }, { 247, 251, 249, 4 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 251, 255, 253, 4 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 },
};
TableEntry g_singleColor5_3_p[256] =
{
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 8, 2, 8 }, { 0, 8, 2, 8 }, { 8, 0, 5, 8 }, { 8, 0, 5, 8 }, { 8, 0, 5, 8 }, { 8, 8, 8, 0 },
{ 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 16, 10, 8 }, { 0, 33, 11, 33 }, { 16, 8, 13, 8 }, { 16, 8, 13, 8 }, { 16, 8, 13, 8 }, { 16, 16, 16, 0 },
{ 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 24, 18, 8 }, { 8, 41, 19, 33 }, { 24, 16, 21, 8 }, { 24, 16, 21, 8 }, { 33, 0, 22, 33 }, { 24, 24, 24, 0 },
{ 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 33, 27, 9 }, { 24, 33, 27, 9 }, { 24, 33, 27, 9 }, { 24, 41, 29, 17 }, { 33, 24, 30, 9 }, { 33, 24, 30, 9 },
{ 24, 49, 32, 25 }, { 33, 33, 33, 0 }, { 33, 33, 33, 0 }, { 33, 41, 35, 8 }, { 33, 41, 35, 8 }, { 41, 33, 38, 8 }, { 41, 33, 38, 8 }, { 41, 33, 38, 8 },
{ 49, 24, 40, 25 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 41, 49, 43, 8 }, { 33, 66, 44, 33 }, { 49, 41, 46, 8 }, { 49, 41, 46, 8 }, { 49, 41, 46, 8 },
{ 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 57, 51, 8 }, { 41, 74, 52, 33 }, { 57, 49, 54, 8 }, { 57, 49, 54, 8 }, { 66, 33, 55, 33 },
{ 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 66, 60, 9 }, { 57, 66, 60, 9 }, { 57, 66, 60, 9 }, { 57, 74, 62, 17 }, { 66, 57, 63, 9 },
{ 66, 57, 63, 9 }, { 57, 82, 65, 25 }, { 66, 66, 66, 0 }, { 66, 66, 66, 0 }, { 66, 74, 68, 8 }, { 66, 74, 68, 8 }, { 74, 66, 71, 8 }, { 74, 66, 71, 8 },
{ 74, 66, 71, 8 }, { 82, 57, 73, 25 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 74, 82, 76, 8 }, { 66, 99, 77, 33 }, { 82, 74, 79, 8 }, { 82, 74, 79, 8 },
{ 82, 74, 79, 8 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 90, 84, 8 }, { 74, 107, 85, 33 }, { 90, 82, 87, 8 }, { 90, 82, 87, 8 },
{ 99, 66, 88, 33 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 99, 93, 9 }, { 90, 99, 93, 9 }, { 90, 99, 93, 9 }, { 90, 107, 95, 17 },
{ 99, 90, 96, 9 }, { 99, 90, 96, 9 }, { 90, 115, 98, 25 }, { 99, 99, 99, 0 }, { 99, 99, 99, 0 }, { 99, 107, 101, 8 }, { 99, 107, 101, 8 }, { 107, 99, 104, 8 },
{ 107, 99, 104, 8 }, { 107, 99, 104, 8 }, { 115, 90, 106, 25 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 107, 115, 109, 8 }, { 99, 132, 110, 33 }, { 115, 107, 112, 8 },
{ 115, 107, 112, 8 }, { 115, 107, 112, 8 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 123, 117, 8 }, { 107, 140, 118, 33 }, { 123, 115, 120, 8 },
{ 123, 115, 120, 8 }, { 132, 99, 121, 33 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 132, 126, 9 }, { 123, 132, 126, 9 }, { 123, 132, 126, 9 },
{ 123, 140, 128, 17 }, { 132, 123, 129, 9 }, { 132, 123, 129, 9 }, { 123, 148, 131, 25 }, { 132, 132, 132, 0 }, { 132, 132, 132, 0 }, { 132, 140, 134, 8 }, { 132, 140, 134, 8 },
{ 140, 132, 137, 8 }, { 140, 132, 137, 8 }, { 140, 132, 137, 8 }, { 148, 123, 139, 25 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 140, 148, 142, 8 }, { 132, 165, 143, 33 },
{ 148, 140, 145, 8 }, { 148, 140, 145, 8 }, { 148, 140, 145, 8 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 156, 150, 8 }, { 140, 173, 151, 33 },
{ 156, 148, 153, 8 }, { 156, 148, 153, 8 }, { 165, 132, 154, 33 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 165, 159, 9 }, { 156, 165, 159, 9 },
{ 156, 165, 159, 9 }, { 156, 173, 161, 17 }, { 165, 156, 162, 9 }, { 165, 156, 162, 9 }, { 156, 181, 164, 25 }, { 165, 165, 165, 0 }, { 165, 165, 165, 0 }, { 165, 173, 167, 8 },
{ 165, 173, 167, 8 }, { 173, 165, 170, 8 }, { 173, 165, 170, 8 }, { 173, 165, 170, 8 }, { 181, 156, 172, 25 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, { 173, 181, 175, 8 },
{ 165, 198, 176, 33 }, { 181, 173, 178, 8 }, { 181, 173, 178, 8 }, { 181, 173, 178, 8 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 189, 183, 8 },
{ 173, 206, 184, 33 }, { 189, 181, 186, 8 }, { 189, 181, 186, 8 }, { 198, 165, 187, 33 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 198, 192, 9 },
{ 189, 198, 192, 9 }, { 189, 198, 192, 9 }, { 189, 206, 194, 17 }, { 198, 189, 195, 9 }, { 198, 189, 195, 9 }, { 189, 214, 197, 25 }, { 198, 198, 198, 0 }, { 198, 198, 198, 0 },
{ 198, 206, 200, 8 }, { 198, 206, 200, 8 }, { 206, 198, 203, 8 }, { 206, 198, 203, 8 }, { 206, 198, 203, 8 }, { 214, 189, 205, 25 }, { 206, 206, 206, 0 }, { 206, 206, 206, 0 },
{ 206, 214, 208, 8 }, { 198, 231, 209, 33 }, { 214, 206, 211, 8 }, { 214, 206, 211, 8 }, { 214, 206, 211, 8 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 },
{ 214, 222, 216, 8 }, { 206, 239, 217, 33 }, { 222, 214, 219, 8 }, { 222, 214, 219, 8 }, { 231, 198, 220, 33 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 },
{ 222, 231, 225, 9 }, { 222, 231, 225, 9 }, { 222, 231, 225, 9 }, { 222, 239, 227, 17 }, { 231, 222, 228, 9 }, { 231, 222, 228, 9 }, { 222, 247, 230, 25 }, { 231, 231, 231, 0 },
{ 231, 231, 231, 0 }, { 231, 239, 233, 8 }, { 231, 239, 233, 8 }, { 239, 231, 236, 8 }, { 239, 231, 236, 8 }, { 239, 231, 236, 8 }, { 247, 222, 238, 25 }, { 239, 239, 239, 0 },
{ 239, 239, 239, 0 }, { 239, 247, 241, 8 }, { 239, 247, 241, 8 }, { 247, 239, 244, 8 }, { 247, 239, 244, 8 }, { 247, 239, 244, 8 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 },
{ 247, 247, 247, 0 }, { 247, 255, 249, 8 }, { 247, 255, 249, 8 }, { 255, 247, 252, 8 }, { 255, 247, 252, 8 }, { 255, 247, 252, 8 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 },
};
TableEntry g_singleColor6_3_p[256] =
{
{ 0, 0, 0, 0 }, { 0, 4, 1, 4 }, { 4, 0, 2, 4 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 4, 8, 5, 4 }, { 8, 4, 6, 4 }, { 8, 8, 8, 0 },
{ 8, 8, 8, 0 }, { 8, 12, 9, 4 }, { 12, 8, 10, 4 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 12, 16, 13, 4 }, { 16, 12, 14, 4 }, { 16, 16, 16, 0 },
{ 16, 16, 16, 0 }, { 16, 20, 17, 4 }, { 20, 16, 18, 4 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 20, 24, 21, 4 }, { 24, 20, 22, 4 }, { 24, 24, 24, 0 },
{ 24, 24, 24, 0 }, { 24, 28, 25, 4 }, { 28, 24, 26, 4 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 28, 32, 29, 4 }, { 32, 28, 30, 4 }, { 32, 32, 32, 0 },
{ 32, 32, 32, 0 }, { 32, 36, 33, 4 }, { 36, 32, 34, 4 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 36, 40, 37, 4 }, { 40, 36, 38, 4 }, { 40, 40, 40, 0 },
{ 40, 40, 40, 0 }, { 40, 44, 41, 4 }, { 44, 40, 42, 4 }, { 32, 65, 43, 33 }, { 44, 44, 44, 0 }, { 44, 48, 45, 4 }, { 48, 44, 46, 4 }, { 36, 69, 47, 33 },
{ 48, 48, 48, 0 }, { 48, 52, 49, 4 }, { 52, 48, 50, 4 }, { 44, 65, 51, 21 }, { 52, 52, 52, 0 }, { 52, 56, 53, 4 }, { 56, 52, 54, 4 }, { 48, 69, 55, 21 },
{ 56, 56, 56, 0 }, { 56, 60, 57, 4 }, { 60, 56, 58, 4 }, { 56, 65, 59, 9 }, { 60, 60, 60, 0 }, { 60, 65, 61, 5 }, { 65, 56, 62, 9 }, { 65, 60, 63, 5 },
{ 60, 73, 64, 13 }, { 65, 65, 65, 0 }, { 65, 69, 66, 4 }, { 69, 65, 67, 4 }, { 73, 60, 68, 13 }, { 69, 69, 69, 0 }, { 69, 73, 70, 4 }, { 73, 69, 71, 4 },
{ 81, 56, 72, 25 }, { 73, 73, 73, 0 }, { 73, 77, 74, 4 }, { 77, 73, 75, 4 }, { 85, 60, 76, 25 }, { 77, 77, 77, 0 }, { 77, 81, 78, 4 }, { 81, 77, 79, 4 },
{ 81, 81, 81, 0 }, { 81, 81, 81, 0 }, { 81, 85, 82, 4 }, { 85, 81, 83, 4 }, { 85, 85, 85, 0 }, { 85, 85, 85, 0 }, { 85, 89, 86, 4 }, { 89, 85, 87, 4 },
{ 89, 89, 89, 0 }, { 89, 89, 89, 0 }, { 89, 93, 90, 4 }, { 93, 89, 91, 4 }, { 93, 93, 93, 0 }, { 93, 93, 93, 0 }, { 93, 97, 94, 4 }, { 97, 93, 95, 4 },
{ 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 97, 101, 98, 4 }, { 101, 97, 99, 4 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 101, 105, 102, 4 }, { 105, 101, 103, 4 },
{ 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 105, 109, 106, 4 }, { 109, 105, 107, 4 }, { 97, 130, 108, 33 }, { 109, 109, 109, 0 }, { 109, 113, 110, 4 }, { 113, 109, 111, 4 },
{ 101, 134, 112, 33 }, { 113, 113, 113, 0 }, { 113, 117, 114, 4 }, { 117, 113, 115, 4 }, { 109, 130, 116, 21 }, { 117, 117, 117, 0 }, { 117, 121, 118, 4 }, { 121, 117, 119, 4 },
{ 113, 134, 120, 21 }, { 121, 121, 121, 0 }, { 121, 125, 122, 4 }, { 125, 121, 123, 4 }, { 121, 130, 124, 9 }, { 125, 125, 125, 0 }, { 125, 130, 126, 5 }, { 130, 121, 127, 9 },
{ 130, 125, 128, 5 }, { 125, 138, 129, 13 }, { 130, 130, 130, 0 }, { 130, 134, 131, 4 }, { 134, 130, 132, 4 }, { 138, 125, 133, 13 }, { 134, 134, 134, 0 }, { 134, 138, 135, 4 },
{ 138, 134, 136, 4 }, { 146, 121, 137, 25 }, { 138, 138, 138, 0 }, { 138, 142, 139, 4 }, { 142, 138, 140, 4 }, { 150, 125, 141, 25 }, { 142, 142, 142, 0 }, { 142, 146, 143, 4 },
{ 146, 142, 144, 4 }, { 146, 146, 146, 0 }, { 146, 146, 146, 0 }, { 146, 150, 147, 4 }, { 150, 146, 148, 4 }, { 150, 150, 150, 0 }, { 150, 150, 150, 0 }, { 150, 154, 151, 4 },
{ 154, 150, 152, 4 }, { 154, 154, 154, 0 }, { 154, 154, 154, 0 }, { 154, 158, 155, 4 }, { 158, 154, 156, 4 }, { 158, 158, 158, 0 }, { 158, 158, 158, 0 }, { 158, 162, 159, 4 },
{ 162, 158, 160, 4 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 162, 166, 163, 4 }, { 166, 162, 164, 4 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 }, { 166, 170, 167, 4 },
{ 170, 166, 168, 4 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 170, 174, 171, 4 }, { 174, 170, 172, 4 }, { 162, 195, 173, 33 }, { 174, 174, 174, 0 }, { 174, 178, 175, 4 },
{ 178, 174, 176, 4 }, { 166, 199, 177, 33 }, { 178, 178, 178, 0 }, { 178, 182, 179, 4 }, { 182, 178, 180, 4 }, { 174, 195, 181, 21 }, { 182, 182, 182, 0 }, { 182, 186, 183, 4 },
{ 186, 182, 184, 4 }, { 178, 199, 185, 21 }, { 186, 186, 186, 0 }, { 186, 190, 187, 4 }, { 190, 186, 188, 4 }, { 186, 195, 189, 9 }, { 190, 190, 190, 0 }, { 190, 195, 191, 5 },
{ 195, 186, 192, 9 }, { 195, 190, 193, 5 }, { 190, 203, 194, 13 }, { 195, 195, 195, 0 }, { 195, 199, 196, 4 }, { 199, 195, 197, 4 }, { 203, 190, 198, 13 }, { 199, 199, 199, 0 },
{ 199, 203, 200, 4 }, { 203, 199, 201, 4 }, { 211, 186, 202, 25 }, { 203, 203, 203, 0 }, { 203, 207, 204, 4 }, { 207, 203, 205, 4 }, { 215, 190, 206, 25 }, { 207, 207, 207, 0 },
{ 207, 211, 208, 4 }, { 211, 207, 209, 4 }, { 211, 211, 211, 0 }, { 211, 211, 211, 0 }, { 211, 215, 212, 4 }, { 215, 211, 213, 4 }, { 215, 215, 215, 0 }, { 215, 215, 215, 0 },
{ 215, 219, 216, 4 }, { 219, 215, 217, 4 }, { 219, 219, 219, 0 }, { 219, 219, 219, 0 }, { 219, 223, 220, 4 }, { 223, 219, 221, 4 }, { 223, 223, 223, 0 }, { 223, 223, 223, 0 },
{ 223, 227, 224, 4 }, { 227, 223, 225, 4 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 227, 231, 228, 4 }, { 231, 227, 229, 4 }, { 231, 231, 231, 0 }, { 231, 231, 231, 0 },
{ 231, 235, 232, 4 }, { 235, 231, 233, 4 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 235, 239, 236, 4 }, { 239, 235, 237, 4 }, { 239, 239, 239, 0 }, { 239, 239, 239, 0 },
{ 239, 243, 240, 4 }, { 243, 239, 241, 4 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 243, 247, 244, 4 }, { 247, 243, 245, 4 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 },
{ 247, 251, 248, 4 }, { 251, 247, 249, 4 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 251, 255, 252, 4 }, { 255, 251, 253, 4 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 },
};
TableEntry g_singleColor5_2_p[256] =
{
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 8, 4, 8 }, { 0, 8, 4, 8 }, { 0, 8, 4, 8 }, { 8, 8, 8, 0 }, { 8, 8, 8, 0 },
{ 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 16, 12, 8 }, { 8, 16, 12, 8 }, { 8, 16, 12, 8 }, { 16, 16, 16, 0 }, { 16, 16, 16, 0 },
{ 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 24, 20, 8 }, { 16, 24, 20, 8 }, { 16, 24, 20, 8 }, { 24, 24, 24, 0 }, { 24, 24, 24, 0 },
{ 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 41, 32, 17 },
{ 24, 41, 32, 17 }, { 33, 33, 33, 0 }, { 33, 33, 33, 0 }, { 24, 49, 36, 25 }, { 24, 49, 36, 25 }, { 33, 41, 37, 8 }, { 33, 41, 37, 8 }, { 24, 57, 40, 33 },
{ 24, 57, 40, 33 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 41, 49, 45, 8 }, { 41, 49, 45, 8 }, { 41, 49, 45, 8 }, { 49, 49, 49, 0 },
{ 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 57, 53, 8 }, { 49, 57, 53, 8 }, { 49, 57, 53, 8 }, { 57, 57, 57, 0 },
{ 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 },
{ 57, 74, 65, 17 }, { 57, 74, 65, 17 }, { 66, 66, 66, 0 }, { 66, 66, 66, 0 }, { 57, 82, 69, 25 }, { 57, 82, 69, 25 }, { 66, 74, 70, 8 }, { 66, 74, 70, 8 },
{ 57, 90, 73, 33 }, { 57, 90, 73, 33 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 74, 82, 78, 8 }, { 74, 82, 78, 8 }, { 74, 82, 78, 8 },
{ 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 90, 86, 8 }, { 82, 90, 86, 8 }, { 82, 90, 86, 8 },
{ 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 99, 94, 9 }, { 90, 99, 94, 9 }, { 90, 99, 94, 9 },
{ 90, 99, 94, 9 }, { 90, 107, 98, 17 }, { 90, 107, 98, 17 }, { 99, 99, 99, 0 }, { 99, 99, 99, 0 }, { 90, 115, 102, 25 }, { 90, 115, 102, 25 }, { 99, 107, 103, 8 },
{ 99, 107, 103, 8 }, { 90, 123, 106, 33 }, { 90, 123, 106, 33 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 107, 115, 111, 8 }, { 107, 115, 111, 8 },
{ 107, 115, 111, 8 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 123, 119, 8 }, { 115, 123, 119, 8 },
{ 115, 123, 119, 8 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 132, 127, 9 }, { 123, 132, 127, 9 },
{ 123, 132, 127, 9 }, { 123, 132, 127, 9 }, { 123, 140, 131, 17 }, { 123, 140, 131, 17 }, { 132, 132, 132, 0 }, { 132, 132, 132, 0 }, { 123, 148, 135, 25 }, { 123, 148, 135, 25 },
{ 132, 140, 136, 8 }, { 132, 140, 136, 8 }, { 123, 156, 139, 33 }, { 123, 156, 139, 33 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 140, 148, 144, 8 },
{ 140, 148, 144, 8 }, { 140, 148, 144, 8 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 156, 152, 8 },
{ 148, 156, 152, 8 }, { 148, 156, 152, 8 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 165, 160, 9 },
{ 156, 165, 160, 9 }, { 156, 165, 160, 9 }, { 156, 165, 160, 9 }, { 156, 173, 164, 17 }, { 156, 173, 164, 17 }, { 165, 165, 165, 0 }, { 165, 165, 165, 0 }, { 156, 181, 168, 25 },
{ 156, 181, 168, 25 }, { 165, 173, 169, 8 }, { 165, 173, 169, 8 }, { 156, 189, 172, 33 }, { 156, 189, 172, 33 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 },
{ 173, 181, 177, 8 }, { 173, 181, 177, 8 }, { 173, 181, 177, 8 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 },
{ 181, 189, 185, 8 }, { 181, 189, 185, 8 }, { 181, 189, 185, 8 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 },
{ 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 206, 197, 17 }, { 189, 206, 197, 17 }, { 198, 198, 198, 0 }, { 198, 198, 198, 0 },
{ 189, 214, 201, 25 }, { 189, 214, 201, 25 }, { 198, 206, 202, 8 }, { 198, 206, 202, 8 }, { 189, 222, 205, 33 }, { 189, 222, 205, 33 }, { 206, 206, 206, 0 }, { 206, 206, 206, 0 },
{ 206, 206, 206, 0 }, { 206, 214, 210, 8 }, { 206, 214, 210, 8 }, { 206, 214, 210, 8 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 },
{ 214, 214, 214, 0 }, { 214, 222, 218, 8 }, { 214, 222, 218, 8 }, { 214, 222, 218, 8 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 },
{ 222, 222, 222, 0 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 239, 230, 17 }, { 222, 239, 230, 17 }, { 231, 231, 231, 0 },
{ 231, 231, 231, 0 }, { 222, 247, 234, 25 }, { 222, 247, 234, 25 }, { 231, 239, 235, 8 }, { 231, 239, 235, 8 }, { 222, 255, 238, 33 }, { 222, 255, 238, 33 }, { 239, 239, 239, 0 },
{ 239, 239, 239, 0 }, { 239, 239, 239, 0 }, { 239, 247, 243, 8 }, { 239, 247, 243, 8 }, { 239, 247, 243, 8 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 },
{ 247, 247, 247, 0 }, { 247, 247, 247, 0 }, { 247, 255, 251, 8 }, { 247, 255, 251, 8 }, { 247, 255, 251, 8 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 },
};
TableEntry g_singleColor6_2_p[256] =
{
{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 4, 2, 4 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 4, 8, 6, 4 }, { 8, 8, 8, 0 },
{ 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 12, 10, 4 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 12, 16, 14, 4 }, { 16, 16, 16, 0 },
{ 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 20, 18, 4 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 20, 24, 22, 4 }, { 24, 24, 24, 0 },
{ 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 28, 26, 4 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 28, 32, 30, 4 }, { 32, 32, 32, 0 },
{ 32, 32, 32, 0 }, { 32, 32, 32, 0 }, { 32, 36, 34, 4 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 36, 40, 38, 4 }, { 40, 40, 40, 0 },
{ 40, 40, 40, 0 }, { 40, 40, 40, 0 }, { 40, 44, 42, 4 }, { 44, 44, 44, 0 }, { 44, 44, 44, 0 }, { 44, 44, 44, 0 }, { 44, 48, 46, 4 }, { 48, 48, 48, 0 },
{ 48, 48, 48, 0 }, { 48, 48, 48, 0 }, { 48, 52, 50, 4 }, { 52, 52, 52, 0 }, { 52, 52, 52, 0 }, { 52, 52, 52, 0 }, { 52, 56, 54, 4 }, { 56, 56, 56, 0 },
{ 56, 56, 56, 0 }, { 56, 56, 56, 0 }, { 56, 60, 58, 4 }, { 60, 60, 60, 0 }, { 60, 60, 60, 0 }, { 60, 60, 60, 0 }, { 60, 65, 62, 5 }, { 60, 65, 62, 5 },
{ 60, 69, 64, 9 }, { 65, 65, 65, 0 }, { 60, 73, 66, 13 }, { 65, 69, 67, 4 }, { 60, 77, 68, 17 }, { 69, 69, 69, 0 }, { 60, 81, 70, 21 }, { 69, 73, 71, 4 },
{ 60, 85, 72, 25 }, { 73, 73, 73, 0 }, { 60, 89, 74, 29 }, { 73, 77, 75, 4 }, { 60, 93, 76, 33 }, { 77, 77, 77, 0 }, { 77, 77, 77, 0 }, { 77, 81, 79, 4 },
{ 81, 81, 81, 0 }, { 81, 81, 81, 0 }, { 81, 81, 81, 0 }, { 81, 85, 83, 4 }, { 85, 85, 85, 0 }, { 85, 85, 85, 0 }, { 85, 85, 85, 0 }, { 85, 89, 87, 4 },
{ 89, 89, 89, 0 }, { 89, 89, 89, 0 }, { 89, 89, 89, 0 }, { 89, 93, 91, 4 }, { 93, 93, 93, 0 }, { 93, 93, 93, 0 }, { 93, 93, 93, 0 }, { 93, 97, 95, 4 },
{ 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 97, 101, 99, 4 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 101, 105, 103, 4 },
{ 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 105, 109, 107, 4 }, { 109, 109, 109, 0 }, { 109, 109, 109, 0 }, { 109, 109, 109, 0 }, { 109, 113, 111, 4 },
{ 113, 113, 113, 0 }, { 113, 113, 113, 0 }, { 113, 113, 113, 0 }, { 113, 117, 115, 4 }, { 117, 117, 117, 0 }, { 117, 117, 117, 0 }, { 117, 117, 117, 0 }, { 117, 121, 119, 4 },
{ 121, 121, 121, 0 }, { 121, 121, 121, 0 }, { 121, 121, 121, 0 }, { 121, 125, 123, 4 }, { 125, 125, 125, 0 }, { 125, 125, 125, 0 }, { 125, 125, 125, 0 }, { 125, 130, 127, 5 },
{ 125, 130, 127, 5 }, { 125, 134, 129, 9 }, { 130, 130, 130, 0 }, { 125, 138, 131, 13 }, { 130, 134, 132, 4 }, { 125, 142, 133, 17 }, { 134, 134, 134, 0 }, { 125, 146, 135, 21 },
{ 134, 138, 136, 4 }, { 125, 150, 137, 25 }, { 138, 138, 138, 0 }, { 125, 154, 139, 29 }, { 138, 142, 140, 4 }, { 125, 158, 141, 33 }, { 142, 142, 142, 0 }, { 142, 142, 142, 0 },
{ 142, 146, 144, 4 }, { 146, 146, 146, 0 }, { 146, 146, 146, 0 }, { 146, 146, 146, 0 }, { 146, 150, 148, 4 }, { 150, 150, 150, 0 }, { 150, 150, 150, 0 }, { 150, 150, 150, 0 },
{ 150, 154, 152, 4 }, { 154, 154, 154, 0 }, { 154, 154, 154, 0 }, { 154, 154, 154, 0 }, { 154, 158, 156, 4 }, { 158, 158, 158, 0 }, { 158, 158, 158, 0 }, { 158, 158, 158, 0 },
{ 158, 162, 160, 4 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 162, 166, 164, 4 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 },
{ 166, 170, 168, 4 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 170, 174, 172, 4 }, { 174, 174, 174, 0 }, { 174, 174, 174, 0 }, { 174, 174, 174, 0 },
{ 174, 178, 176, 4 }, { 178, 178, 178, 0 }, { 178, 178, 178, 0 }, { 178, 178, 178, 0 }, { 178, 182, 180, 4 }, { 182, 182, 182, 0 }, { 182, 182, 182, 0 }, { 182, 182, 182, 0 },
{ 182, 186, 184, 4 }, { 186, 186, 186, 0 }, { 186, 186, 186, 0 }, { 186, 186, 186, 0 }, { 186, 190, 188, 4 }, { 190, 190, 190, 0 }, { 190, 190, 190, 0 }, { 190, 190, 190, 0 },
{ 190, 195, 192, 5 }, { 190, 195, 192, 5 }, { 190, 199, 194, 9 }, { 195, 195, 195, 0 }, { 190, 203, 196, 13 }, { 195, 199, 197, 4 }, { 190, 207, 198, 17 }, { 199, 199, 199, 0 },
{ 190, 211, 200, 21 }, { 199, 203, 201, 4 }, { 190, 215, 202, 25 }, { 203, 203, 203, 0 }, { 190, 219, 204, 29 }, { 203, 207, 205, 4 }, { 190, 223, 206, 33 }, { 207, 207, 207, 0 },
{ 207, 207, 207, 0 }, { 207, 211, 209, 4 }, { 211, 211, 211, 0 }, { 211, 211, 211, 0 }, { 211, 211, 211, 0 }, { 211, 215, 213, 4 }, { 215, 215, 215, 0 }, { 215, 215, 215, 0 },
{ 215, 215, 215, 0 }, { 215, 219, 217, 4 }, { 219, 219, 219, 0 }, { 219, 219, 219, 0 }, { 219, 219, 219, 0 }, { 219, 223, 221, 4 }, { 223, 223, 223, 0 }, { 223, 223, 223, 0 },
{ 223, 223, 223, 0 }, { 223, 227, 225, 4 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 227, 231, 229, 4 }, { 231, 231, 231, 0 }, { 231, 231, 231, 0 },
{ 231, 231, 231, 0 }, { 231, 235, 233, 4 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 235, 239, 237, 4 }, { 239, 239, 239, 0 }, { 239, 239, 239, 0 },
{ 239, 239, 239, 0 }, { 239, 243, 241, 4 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 243, 247, 245, 4 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 },
{ 247, 247, 247, 0 }, { 247, 251, 249, 4 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 251, 255, 253, 4 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 },
};
}}}

View File

@@ -0,0 +1,48 @@
/*
Convection Texture Tools
Copyright (c) 2018-2019 Eric Lasota
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.
-------------------------------------------------------------------------------------
Portions based on DirectX Texture Library (DirectXTex)
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
http://go.microsoft.com/fwlink/?LinkId=248926
*/
#include "ConvectionKernels_Config.h"
#if defined(CVTT_SINGLE_FILE)
#define CVTT_SINGLE_FILE_IMPL
#include "ConvectionKernels_API.cpp"
#include "ConvectionKernels_BC67.cpp"
#include "ConvectionKernels_BC6H_IO.cpp"
#include "ConvectionKernels_BC7_PrioData.cpp"
#include "ConvectionKernels_BCCommon.cpp"
#include "ConvectionKernels_ETC.cpp"
#include "ConvectionKernels_IndexSelector.cpp"
#include "ConvectionKernels_S3TC.cpp"
#include "ConvectionKernels_Util.cpp"
#endif

View File

@@ -0,0 +1,121 @@
#pragma once
#include "ConvectionKernels_Util.h"
namespace cvtt
{
namespace Internal
{
template<int TVectorSize>
class UnfinishedEndpoints
{
public:
typedef ParallelMath::Float MFloat;
typedef ParallelMath::UInt16 MUInt16;
typedef ParallelMath::UInt15 MUInt15;
typedef ParallelMath::SInt16 MSInt16;
typedef ParallelMath::SInt32 MSInt32;
UnfinishedEndpoints()
{
}
UnfinishedEndpoints(const MFloat *base, const MFloat *offset)
{
for (int ch = 0; ch < TVectorSize; ch++)
m_base[ch] = base[ch];
for (int ch = 0; ch < TVectorSize; ch++)
m_offset[ch] = offset[ch];
}
UnfinishedEndpoints(const UnfinishedEndpoints& other)
{
for (int ch = 0; ch < TVectorSize; ch++)
m_base[ch] = other.m_base[ch];
for (int ch = 0; ch < TVectorSize; ch++)
m_offset[ch] = other.m_offset[ch];
}
void FinishHDRUnsigned(int tweak, int range, MSInt16 *outEP0, MSInt16 *outEP1, ParallelMath::RoundTowardNearestForScope *roundingMode)
{
float tweakFactors[2];
Util::ComputeTweakFactors(tweak, range, tweakFactors);
for (int ch = 0; ch < TVectorSize; ch++)
{
MUInt15 channelEPs[2];
for (int epi = 0; epi < 2; epi++)
{
MFloat f = ParallelMath::Clamp(m_base[ch] + m_offset[ch] * tweakFactors[epi], 0.0f, 31743.0f);
channelEPs[epi] = ParallelMath::RoundAndConvertToU15(f, roundingMode);
}
outEP0[ch] = ParallelMath::LosslessCast<MSInt16>::Cast(channelEPs[0]);
outEP1[ch] = ParallelMath::LosslessCast<MSInt16>::Cast(channelEPs[1]);
}
}
void FinishHDRSigned(int tweak, int range, MSInt16* outEP0, MSInt16* outEP1, ParallelMath::RoundTowardNearestForScope* roundingMode)
{
float tweakFactors[2];
Util::ComputeTweakFactors(tweak, range, tweakFactors);
for (int ch = 0; ch < TVectorSize; ch++)
{
MSInt16 channelEPs[2];
for (int epi = 0; epi < 2; epi++)
{
MFloat f = ParallelMath::Clamp(m_base[ch] + m_offset[ch] * tweakFactors[epi], -31743.0f, 31743.0f);
channelEPs[epi] = ParallelMath::RoundAndConvertToS16(f, roundingMode);
}
outEP0[ch] = channelEPs[0];
outEP1[ch] = channelEPs[1];
}
}
void FinishLDR(int tweak, int range, MUInt15* outEP0, MUInt15* outEP1)
{
ParallelMath::RoundTowardNearestForScope roundingMode;
float tweakFactors[2];
Util::ComputeTweakFactors(tweak, range, tweakFactors);
for (int ch = 0; ch < TVectorSize; ch++)
{
MFloat ep0f = ParallelMath::Clamp(m_base[ch] + m_offset[ch] * tweakFactors[0], 0.0f, 255.0f);
MFloat ep1f = ParallelMath::Clamp(m_base[ch] + m_offset[ch] * tweakFactors[1], 0.0f, 255.0f);
outEP0[ch] = ParallelMath::RoundAndConvertToU15(ep0f, &roundingMode);
outEP1[ch] = ParallelMath::RoundAndConvertToU15(ep1f, &roundingMode);
}
}
template<int TNewVectorSize>
UnfinishedEndpoints<TNewVectorSize> ExpandTo(float filler)
{
MFloat newBase[TNewVectorSize];
MFloat newOffset[TNewVectorSize];
for (int ch = 0; ch < TNewVectorSize && ch < TVectorSize; ch++)
{
newBase[ch] = m_base[ch];
newOffset[ch] = m_offset[ch];
}
MFloat fillerV = ParallelMath::MakeFloat(filler);
for (int ch = TVectorSize; ch < TNewVectorSize; ch++)
{
newBase[ch] = fillerV;
newOffset[ch] = ParallelMath::MakeFloatZero();
}
return UnfinishedEndpoints<TNewVectorSize>(newBase, newOffset);
}
private:
MFloat m_base[TVectorSize];
MFloat m_offset[TVectorSize];
};
}
}

View File

@@ -0,0 +1,88 @@
/*
Convection Texture Tools
Copyright (c) 2018-2019 Eric Lasota
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.
-------------------------------------------------------------------------------------
Portions based on DirectX Texture Library (DirectXTex)
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
http://go.microsoft.com/fwlink/?LinkId=248926
*/
#include "ConvectionKernels_Config.h"
#if !defined(CVTT_SINGLE_FILE) || defined(CVTT_SINGLE_FILE_IMPL)
#include "ConvectionKernels.h"
#include "ConvectionKernels_ParallelMath.h"
#include <algorithm>
namespace cvtt
{
namespace Util
{
// Signed input blocks are converted into unsigned space, with the maximum value being 254
void BiasSignedInput(PixelBlockU8 inputNormalized[ParallelMath::ParallelSize], const PixelBlockS8 inputSigned[ParallelMath::ParallelSize])
{
for (size_t block = 0; block < ParallelMath::ParallelSize; block++)
{
const PixelBlockS8& inputSignedBlock = inputSigned[block];
PixelBlockU8& inputNormalizedBlock = inputNormalized[block];
for (size_t px = 0; px < 16; px++)
{
for (size_t ch = 0; ch < 4; ch++)
inputNormalizedBlock.m_pixels[px][ch] = static_cast<uint8_t>(std::max<int>(inputSignedBlock.m_pixels[px][ch], -127) + 127);
}
}
}
void FillWeights(const Options &options, float channelWeights[4])
{
if (options.flags & Flags::Uniform)
channelWeights[0] = channelWeights[1] = channelWeights[2] = channelWeights[3] = 1.0f;
else
{
channelWeights[0] = options.redWeight;
channelWeights[1] = options.greenWeight;
channelWeights[2] = options.blueWeight;
channelWeights[3] = options.alphaWeight;
}
}
void ComputeTweakFactors(int tweak, int range, float *outFactors)
{
int totalUnits = range - 1;
int minOutsideUnits = ((tweak >> 1) & 1);
int maxOutsideUnits = (tweak & 1);
int insideUnits = totalUnits - minOutsideUnits - maxOutsideUnits;
outFactors[0] = -static_cast<float>(minOutsideUnits) / static_cast<float>(insideUnits);
outFactors[1] = static_cast<float>(maxOutsideUnits) / static_cast<float>(insideUnits) + 1.0f;
}
}
}
#endif

View File

@@ -0,0 +1,21 @@
#pragma once
#include "ConvectionKernels_ParallelMath.h"
namespace cvtt
{
struct PixelBlockU8;
struct PixelBlockS8;
struct Options;
}
namespace cvtt
{
namespace Util
{
// Signed input blocks are converted into unsigned space, with the maximum value being 254
void BiasSignedInput(PixelBlockU8 inputNormalized[ParallelMath::ParallelSize], const PixelBlockS8 inputSigned[ParallelMath::ParallelSize]);
void FillWeights(const Options &options, float channelWeights[4]);
void ComputeTweakFactors(int tweak, int range, float *outFactors);
}
}

45
thirdparty/cvtt/LICENSE.txt vendored Normal file
View File

@@ -0,0 +1,45 @@
Convection Texture Tools Stand-Alone Kernels
Copyright (c) 2018 Eric Lasota
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.
**************************************************************************
Based on DirectX Texture Library
Copyright (c) 2018 Microsoft Corp
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.

View File

@@ -0,0 +1,393 @@
diff --git a/thirdparty/cvtt/ConvectionKernels_BC67.cpp b/thirdparty/cvtt/ConvectionKernels_BC67.cpp
index 021d658c08..011f51570b 100644
--- a/thirdparty/cvtt/ConvectionKernels_BC67.cpp
+++ b/thirdparty/cvtt/ConvectionKernels_BC67.cpp
@@ -76,6 +76,205 @@ namespace cvtt
};
}
+ namespace BC6HData
+ {
+ enum EField
+ {
+ NA, // N/A
+ M, // Mode
+ D, // Shape
+ RW,
+ RX,
+ RY,
+ RZ,
+ GW,
+ GX,
+ GY,
+ GZ,
+ BW,
+ BX,
+ BY,
+ BZ,
+ };
+
+ struct ModeDescriptor
+ {
+ EField m_eField;
+ uint8_t m_uBit;
+ };
+
+ const ModeDescriptor g_modeDescriptors[14][82] =
+ {
+ { // Mode 1 (0x00) - 10 5 5 5
+ { M, 0 },{ M, 1 },{ GY, 4 },{ BY, 4 },{ BZ, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 },
+ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 },
+ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 },
+ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 },
+ { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 },
+ { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 },
+ { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 },
+ { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 },
+ { D, 3 },{ D, 4 },
+ },
+
+ { // Mode 2 (0x01) - 7 6 6 6
+ { M, 0 },{ M, 1 },{ GY, 5 },{ GZ, 4 },{ GZ, 5 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 },
+ { RW, 5 },{ RW, 6 },{ BZ, 0 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 },
+ { GW, 5 },{ GW, 6 },{ BY, 5 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 },
+ { BW, 5 },{ BW, 6 },{ BZ, 3 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 },
+ { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 },
+ { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 },
+ { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 },
+ { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 },
+ { D, 3 },{ D, 4 },
+ },
+
+ { // Mode 3 (0x02) - 11 5 4 4
+ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 },
+ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 },
+ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 },
+ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 },
+ { RW,10 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,10 },
+ { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,10 },
+ { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 },
+ { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 },
+ { D, 3 },{ D, 4 },
+ },
+
+ { // Mode 4 (0x06) - 11 4 5 4
+ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 },
+ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 },
+ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 },
+ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,10 },
+ { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 },
+ { GW,10 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,10 },
+ { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ BZ, 0 },
+ { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ GY, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 },
+ { D, 3 },{ D, 4 },
+ },
+
+ { // Mode 5 (0x0a) - 11 4 4 5
+ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 },
+ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 },
+ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 },
+ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,10 },
+ { BY, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,10 },
+ { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 },
+ { BW,10 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ BZ, 1 },
+ { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ BZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 },
+ { D, 3 },{ D, 4 },
+ },
+
+ { // Mode 6 (0x0e) - 9 5 5 5
+ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 },
+ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 },
+ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 },
+ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 },
+ { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 },
+ { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 },
+ { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 },
+ { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 },
+ { D, 3 },{ D, 4 },
+ },
+
+ { // Mode 7 (0x12) - 8 6 5 5
+ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 },
+ { RW, 5 },{ RW, 6 },{ RW, 7 },{ GZ, 4 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 },
+ { GW, 5 },{ GW, 6 },{ GW, 7 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 },
+ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BZ, 3 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 },
+ { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 },
+ { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 },
+ { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 },
+ { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 },
+ { D, 3 },{ D, 4 },
+ },
+
+ { // Mode 8 (0x16) - 8 5 6 5
+ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 },
+ { RW, 5 },{ RW, 6 },{ RW, 7 },{ BZ, 0 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 },
+ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GY, 5 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 },
+ { BW, 5 },{ BW, 6 },{ BW, 7 },{ GZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 },
+ { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 },
+ { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 },
+ { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 },
+ { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 },
+ { D, 3 },{ D, 4 },
+ },
+
+ { // Mode 9 (0x1a) - 8 5 5 6
+ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 },
+ { RW, 5 },{ RW, 6 },{ RW, 7 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 },
+ { GW, 5 },{ GW, 6 },{ GW, 7 },{ BY, 5 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 },
+ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 },
+ { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 },
+ { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 },
+ { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 },
+ { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 },
+ { D, 3 },{ D, 4 },
+ },
+
+ { // Mode 10 (0x1e) - 6 6 6 6
+ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 },
+ { RW, 5 },{ GZ, 4 },{ BZ, 0 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 },
+ { GW, 5 },{ GY, 5 },{ BY, 5 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 },
+ { BW, 5 },{ GZ, 5 },{ BZ, 3 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 },
+ { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 },
+ { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 },
+ { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 },
+ { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 },
+ { D, 3 },{ D, 4 },
+ },
+
+ { // Mode 11 (0x03) - 10 10
+ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 },
+ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 },
+ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 },
+ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 },
+ { RX, 5 },{ RX, 6 },{ RX, 7 },{ RX, 8 },{ RX, 9 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 },
+ { GX, 5 },{ GX, 6 },{ GX, 7 },{ GX, 8 },{ GX, 9 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 },
+ { BX, 5 },{ BX, 6 },{ BX, 7 },{ BX, 8 },{ BX, 9 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },
+ { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },
+ { NA, 0 },{ NA, 0 },
+ },
+
+ { // Mode 12 (0x07) - 11 9
+ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 },
+ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 },
+ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 },
+ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 },
+ { RX, 5 },{ RX, 6 },{ RX, 7 },{ RX, 8 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 },
+ { GX, 5 },{ GX, 6 },{ GX, 7 },{ GX, 8 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 },
+ { BX, 5 },{ BX, 6 },{ BX, 7 },{ BX, 8 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },
+ { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },
+ { NA, 0 },{ NA, 0 },
+ },
+
+ { // Mode 13 (0x0b) - 12 8
+ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 },
+ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 },
+ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 },
+ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 },
+ { RX, 5 },{ RX, 6 },{ RX, 7 },{ RW,11 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 },
+ { GX, 5 },{ GX, 6 },{ GX, 7 },{ GW,11 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 },
+ { BX, 5 },{ BX, 6 },{ BX, 7 },{ BW,11 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },
+ { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },
+ { NA, 0 },{ NA, 0 },
+ },
+
+ { // Mode 14 (0x0f) - 16 4
+ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 },
+ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 },
+ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 },
+ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,15 },
+ { RW,14 },{ RW,13 },{ RW,12 },{ RW,11 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,15 },
+ { GW,14 },{ GW,13 },{ GW,12 },{ GW,11 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,15 },
+ { BW,14 },{ BW,13 },{ BW,12 },{ BW,11 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },
+ { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },
+ { NA, 0 },{ NA, 0 },
+ },
+ };
+ }
+
namespace BC7Data
{
enum AlphaMode
@@ -2998,9 +3197,9 @@ void cvtt::Internal::BC6HComputer::Pack(uint32_t flags, const PixelBlockF16* inp
const BC7Data::BC6HModeInfo& modeInfo = BC7Data::g_hdrModes[mode];
- BC6H_IO::WriteFunc_t writeFunc = BC6H_IO::g_writeFuncs[mode];
+ const BC6HData::ModeDescriptor *desc = BC6HData::g_modeDescriptors[mode];
- const int headerBits = modeInfo.m_partitioned ? 82 : 65;
+ const size_t headerBits = modeInfo.m_partitioned ? 82 : 65;
for (int subset = 0; subset < 2; subset++)
{
@@ -3017,16 +3216,58 @@ void cvtt::Internal::BC6HComputer::Pack(uint32_t flags, const PixelBlockF16* inp
uint16_t modeID = modeInfo.m_modeID;
PackingVector pv;
+ pv.Init();
- {
- uint32_t header[3];
- writeFunc(header, modeID, partition,
- eps[0][0][0], eps[0][1][0], eps[1][0][0], eps[1][1][0],
- eps[0][0][1], eps[0][1][1], eps[1][0][1], eps[1][1][1],
- eps[0][0][2], eps[0][1][2], eps[1][0][2], eps[1][1][2]
- );
-
- pv.InitPacked(header, headerBits);
+ for (size_t i = 0; i < headerBits; i++) {
+ int32_t codedValue = 0;
+ switch (desc[i].m_eField) {
+ case BC6HData::M:
+ codedValue = modeID;
+ break;
+ case BC6HData::D:
+ codedValue = partition;
+ break;
+ case BC6HData::RW:
+ codedValue = eps[0][0][0];
+ break;
+ case BC6HData::RX:
+ codedValue = eps[0][1][0];
+ break;
+ case BC6HData::RY:
+ codedValue = eps[1][0][0];
+ break;
+ case BC6HData::RZ:
+ codedValue = eps[1][1][0];
+ break;
+ case BC6HData::GW:
+ codedValue = eps[0][0][1];
+ break;
+ case BC6HData::GX:
+ codedValue = eps[0][1][1];
+ break;
+ case BC6HData::GY:
+ codedValue = eps[1][0][1];
+ break;
+ case BC6HData::GZ:
+ codedValue = eps[1][1][1];
+ break;
+ case BC6HData::BW:
+ codedValue = eps[0][0][2];
+ break;
+ case BC6HData::BX:
+ codedValue = eps[0][1][2];
+ break;
+ case BC6HData::BY:
+ codedValue = eps[1][0][2];
+ break;
+ case BC6HData::BZ:
+ codedValue = eps[1][1][2];
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ pv.Pack(static_cast<uint16_t>((codedValue >> desc[i].m_uBit) & 1), 1);
}
int fixupIndex1 = 0;
@@ -3058,11 +3299,14 @@ void cvtt::Internal::BC6HComputer::SignExtendSingle(int &v, int bits)
void cvtt::Internal::BC6HComputer::UnpackOne(PixelBlockF16 &output, const uint8_t *pBC, bool isSigned)
{
+ UnpackingVector pv;
+ pv.Init(pBC);
+
int numModeBits = 2;
- int modeBits = pBC[0] & 0x3;
+ int modeBits = pv.Unpack(2);
if (modeBits != 0 && modeBits != 1)
{
- modeBits = pBC[0] & 0x1f;
+ modeBits |= pv.Unpack(3) << 2;
numModeBits += 3;
}
@@ -3088,10 +3332,10 @@ void cvtt::Internal::BC6HComputer::UnpackOne(PixelBlockF16 &output, const uint8_
}
const BC7Data::BC6HModeInfo& modeInfo = BC7Data::g_hdrModes[mode];
- const int headerBits = modeInfo.m_partitioned ? 82 : 65;
- const BC6H_IO::ReadFunc_t readFunc = BC6H_IO::g_readFuncs[mode];
+ const size_t headerBits = modeInfo.m_partitioned ? 82 : 65;
+ const BC6HData::ModeDescriptor *desc = BC6HData::g_modeDescriptors[mode];
- uint16_t partition = 0;
+ int32_t partition = 0;
int32_t eps[2][2][3];
for (int subset = 0; subset < 2; subset++)
@@ -3099,24 +3343,55 @@ void cvtt::Internal::BC6HComputer::UnpackOne(PixelBlockF16 &output, const uint8_
for (int ch = 0; ch < 3; ch++)
eps[subset][epi][ch] = 0;
- UnpackingVector pv;
- pv.Init(pBC);
-
- {
- uint32_t header[3];
- uint16_t codedEPs[2][2][3];
- pv.UnpackStart(header, headerBits);
+ for (size_t i = numModeBits; i < headerBits; i++) {
+ int32_t *pCodedValue = NULL;
- readFunc(header, partition,
- codedEPs[0][0][0], codedEPs[0][1][0], codedEPs[1][0][0], codedEPs[1][1][0],
- codedEPs[0][0][1], codedEPs[0][1][1], codedEPs[1][0][1], codedEPs[1][1][1],
- codedEPs[0][0][2], codedEPs[0][1][2], codedEPs[1][0][2], codedEPs[1][1][2]
- );
+ switch (desc[i].m_eField) {
+ case BC6HData::D:
+ pCodedValue = &partition;
+ break;
+ case BC6HData::RW:
+ pCodedValue = &eps[0][0][0];
+ break;
+ case BC6HData::RX:
+ pCodedValue = &eps[0][1][0];
+ break;
+ case BC6HData::RY:
+ pCodedValue = &eps[1][0][0];
+ break;
+ case BC6HData::RZ:
+ pCodedValue = &eps[1][1][0];
+ break;
+ case BC6HData::GW:
+ pCodedValue = &eps[0][0][1];
+ break;
+ case BC6HData::GX:
+ pCodedValue = &eps[0][1][1];
+ break;
+ case BC6HData::GY:
+ pCodedValue = &eps[1][0][1];
+ break;
+ case BC6HData::GZ:
+ pCodedValue = &eps[1][1][1];
+ break;
+ case BC6HData::BW:
+ pCodedValue = &eps[0][0][2];
+ break;
+ case BC6HData::BX:
+ pCodedValue = &eps[0][1][2];
+ break;
+ case BC6HData::BY:
+ pCodedValue = &eps[1][0][2];
+ break;
+ case BC6HData::BZ:
+ pCodedValue = &eps[1][1][2];
+ break;
+ default:
+ assert(false);
+ break;
+ }
- for (int subset = 0; subset < 2; subset++)
- for (int epi = 0; epi < 2; epi++)
- for (int ch = 0; ch < 3; ch++)
- eps[subset][epi][ch] = codedEPs[subset][epi][ch];
+ (*pCodedValue) |= pv.Unpack(1) << desc[i].m_uBit;
}
uint16_t modeID = modeInfo.m_modeID;