mirror of
https://github.com/yuzu-emu/FasTC.git
synced 2025-01-08 06:25:31 +00:00
More refactoring.
Change RGBACluster to be a class that only really persists once per block. When we switch shapes and do operations on them, then we really only need to change which points in the block are accessed. We don't need to do this very often, so just change the mask whenever we need it. This brings us back closer to our original performance, but we're still not where we were when we started refactoring.
This commit is contained in:
parent
fe69dc9fb5
commit
e936cce0cb
|
@ -138,10 +138,9 @@ class CompressionMode {
|
||||||
// be swapped. The final output bits will always be a valid BPTC block.
|
// be swapped. The final output bits will always be a valid BPTC block.
|
||||||
void Pack(Params ¶ms, FasTC::BitStream &stream) const;
|
void Pack(Params ¶ms, FasTC::BitStream &stream) const;
|
||||||
|
|
||||||
// This function compresses a group of clusters into the passed bitstream. The
|
// This function compresses a group of clusters into the passed bitstream.
|
||||||
// size of the clusters array is determined by the BC7 compression mode.
|
double Compress(FasTC::BitStream &stream, const int shapeIdx,
|
||||||
double Compress(FasTC::BitStream &stream,
|
RGBACluster &cluster);
|
||||||
const int shapeIdx, const RGBACluster *clusters);
|
|
||||||
|
|
||||||
// This switch controls the quality of the simulated annealing optimizer. We
|
// This switch controls the quality of the simulated annealing optimizer. We
|
||||||
// will not make more than this many steps regardless of how bad the error is.
|
// will not make more than this many steps regardless of how bad the error is.
|
||||||
|
|
|
@ -79,6 +79,7 @@
|
||||||
#include "TexCompTypes.h"
|
#include "TexCompTypes.h"
|
||||||
#include "BCLookupTables.h"
|
#include "BCLookupTables.h"
|
||||||
#include "RGBAEndpoints.h"
|
#include "RGBAEndpoints.h"
|
||||||
|
#include "Shapes.h"
|
||||||
|
|
||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
using FasTC::BitStream;
|
using FasTC::BitStream;
|
||||||
|
@ -161,17 +162,7 @@ static const char *kBlockStatString[kNumBlockStats] = {
|
||||||
"BlockStat_ModeSevenError",
|
"BlockStat_ModeSevenError",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32 kNumShapes2 = 64;
|
namespace BPTCC {
|
||||||
static const uint16 kShapeMask2[kNumShapes2] = {
|
|
||||||
0xcccc, 0x8888, 0xeeee, 0xecc8, 0xc880, 0xfeec, 0xfec8, 0xec80,
|
|
||||||
0xc800, 0xffec, 0xfe80, 0xe800, 0xffe8, 0xff00, 0xfff0, 0xf000,
|
|
||||||
0xf710, 0x008e, 0x7100, 0x08ce, 0x008c, 0x7310, 0x3100, 0x8cce,
|
|
||||||
0x088c, 0x3110, 0x6666, 0x366c, 0x17e8, 0x0ff0, 0x718e, 0x399c,
|
|
||||||
0xaaaa, 0xf0f0, 0x5a5a, 0x33cc, 0x3c3c, 0x55aa, 0x9696, 0xa55a,
|
|
||||||
0x73ce, 0x13c8, 0x324c, 0x3bdc, 0x6996, 0xc33c, 0x9966, 0x0660,
|
|
||||||
0x0272, 0x04e4, 0x4e40, 0x2720, 0xc936, 0x936c, 0x39c6, 0x639c,
|
|
||||||
0x9336, 0x9cc6, 0x817e, 0xe718, 0xccf0, 0x0fcc, 0x7744, 0xee22
|
|
||||||
};
|
|
||||||
|
|
||||||
static const int kAnchorIdx2[kNumShapes2] = {
|
static const int kAnchorIdx2[kNumShapes2] = {
|
||||||
15, 15, 15, 15, 15, 15, 15, 15,
|
15, 15, 15, 15, 15, 15, 15, 15,
|
||||||
|
@ -184,26 +175,6 @@ static const int kAnchorIdx2[kNumShapes2] = {
|
||||||
15, 15, 15, 15, 15, 2, 2, 15
|
15, 15, 15, 15, 15, 2, 2, 15
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32 kNumShapes3 = 64;
|
|
||||||
static const uint16 kShapeMask3[kNumShapes3][2] = {
|
|
||||||
{0xfecc, 0xf600}, {0xffc8, 0x7300}, {0xff90, 0x3310}, {0xecce, 0x00ce},
|
|
||||||
{0xff00, 0xcc00}, {0xcccc, 0xcc00}, {0xffcc, 0x00cc}, {0xffcc, 0x3300},
|
|
||||||
{0xff00, 0xf000}, {0xfff0, 0xf000}, {0xfff0, 0xff00}, {0xcccc, 0x8888},
|
|
||||||
{0xeeee, 0x8888}, {0xeeee, 0xcccc}, {0xffec, 0xec80}, {0x739c, 0x7310},
|
|
||||||
{0xfec8, 0xc800}, {0x39ce, 0x3100}, {0xfff0, 0xccc0}, {0xfccc, 0x0ccc},
|
|
||||||
{0xeeee, 0xee00}, {0xff88, 0x7700}, {0xeec0, 0xcc00}, {0x7730, 0x3300},
|
|
||||||
{0x0cee, 0x00cc}, {0xffcc, 0xfc88}, {0x6ff6, 0x0660}, {0xff60, 0x6600},
|
|
||||||
{0xcbbc, 0xc88c}, {0xf966, 0xf900}, {0xceec, 0x0cc0}, {0xff10, 0x7310},
|
|
||||||
{0xff80, 0xec80}, {0xccce, 0x08ce}, {0xeccc, 0xec80}, {0x6666, 0x4444},
|
|
||||||
{0x0ff0, 0x0f00}, {0x6db6, 0x4924}, {0x6bd6, 0x4294}, {0xcf3c, 0x0c30},
|
|
||||||
{0xc3fc, 0x03c0}, {0xffaa, 0xff00}, {0xff00, 0x5500}, {0xfcfc, 0xcccc},
|
|
||||||
{0xcccc, 0x0c0c}, {0xf6f6, 0x6666}, {0xaffa, 0x0ff0}, {0xfff0, 0x5550},
|
|
||||||
{0xfaaa, 0xf000}, {0xeeee, 0x0e0e}, {0xf8f8, 0x8888}, {0xfff0, 0x9990},
|
|
||||||
{0xeeee, 0xe00e}, {0x8ff8, 0x8888}, {0xf666, 0xf000}, {0xff00, 0x9900},
|
|
||||||
{0xff66, 0xff00}, {0xcccc, 0xc00c}, {0xcffc, 0xcccc}, {0xf000, 0x9000},
|
|
||||||
{0x8888, 0x0808}, {0xfefe, 0xeeee}, {0xfffa, 0xfff0}, {0x7bde, 0x7310}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32 kWMValues[] = {
|
static const uint32 kWMValues[] = {
|
||||||
0x32b92180, 0x32ba3080, 0x31103200, 0x28103c80,
|
0x32b92180, 0x32ba3080, 0x31103200, 0x28103c80,
|
||||||
0x32bb3080, 0x25903600, 0x3530b900, 0x3b32b180, 0x34b5b98
|
0x32bb3080, 0x25903600, 0x3530b900, 0x3b32b180, 0x34b5b98
|
||||||
|
@ -236,32 +207,6 @@ static inline T sad(const T &a, const T &b) {
|
||||||
return (a > b)? a - b : b - a;
|
return (a > b)? a - b : b - a;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8 GetSubsetForIndex(int idx, const int shapeIdx, const int nSubs) {
|
|
||||||
int subset = 0;
|
|
||||||
|
|
||||||
switch(nSubs) {
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
subset = !!((1 << idx) & kShapeMask2[shapeIdx]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
if(1 << idx & kShapeMask3[shapeIdx][0])
|
|
||||||
subset = 1 + !!((1 << idx) & kShapeMask3[shapeIdx][1]);
|
|
||||||
else
|
|
||||||
subset = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return subset;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32 GetAnchorIndexForSubset(
|
static uint32 GetAnchorIndexForSubset(
|
||||||
int subset, const int shapeIdx, const int nSubsets
|
int subset, const int shapeIdx, const int nSubsets
|
||||||
) {
|
) {
|
||||||
|
@ -304,8 +249,6 @@ static void insert(T* buf, int bufSz, T newVal, int idx = 0) {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline void swap(T &a, T &b) { T t = a; a = b; b = t; }
|
static inline void swap(T &a, T &b) { T t = a; a = b; b = t; }
|
||||||
|
|
||||||
namespace BPTCC {
|
|
||||||
|
|
||||||
const uint32 kInterpolationValues[4][16][2] = {
|
const uint32 kInterpolationValues[4][16][2] = {
|
||||||
{ {64, 0}, {33, 31}, {0, 64}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
|
{ {64, 0}, {33, 31}, {0, 64}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
|
||||||
{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} },
|
{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} },
|
||||||
|
@ -806,14 +749,14 @@ double CompressionMode::CompressCluster(
|
||||||
return cluster.GetNumPoints() * bestErr;
|
return cluster.GetNumPoints() * bestErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
RGBACluster rgbCluster;
|
RGBACluster rgbCluster(cluster);
|
||||||
float alphaVals[kMaxNumDataPoints] = {0};
|
float alphaVals[kMaxNumDataPoints] = {0};
|
||||||
|
|
||||||
float alphaMin = FLT_MAX, alphaMax = -FLT_MAX;
|
float alphaMin = FLT_MAX, alphaMax = -FLT_MAX;
|
||||||
for(uint32 i = 0; i < cluster.GetNumPoints(); i++) {
|
for(uint32 i = 0; i < rgbCluster.GetNumPoints(); i++) {
|
||||||
|
|
||||||
RGBAVector v = cluster.GetPoint(i);
|
RGBAVector &v = rgbCluster.Point(i);
|
||||||
switch(GetRotationMode()) {
|
switch(this->GetRotationMode()) {
|
||||||
default:
|
default:
|
||||||
case 0:
|
case 0:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
|
@ -837,8 +780,6 @@ double CompressionMode::CompressCluster(
|
||||||
|
|
||||||
alphaMin = std::min(alphaVals[i], alphaMin);
|
alphaMin = std::min(alphaVals[i], alphaMin);
|
||||||
alphaMax = std::max(alphaVals[i], alphaMax);
|
alphaMax = std::max(alphaVals[i], alphaMax);
|
||||||
|
|
||||||
rgbCluster.AddPoint(v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 dummyPbit = 0;
|
uint8 dummyPbit = 0;
|
||||||
|
@ -1087,19 +1028,18 @@ double CompressionMode::CompressCluster(
|
||||||
const uint32 nBuckets = (1 << GetNumberOfBitsPerIndex());
|
const uint32 nBuckets = (1 << GetNumberOfBitsPerIndex());
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
RGBAVector avg = cluster.GetAvg();
|
|
||||||
RGBADir axis;
|
RGBADir axis;
|
||||||
::GetPrincipalAxis(cluster.GetNumPoints(), cluster.GetPoints(), axis, NULL, NULL);
|
cluster.GetPrincipalAxis(axis, NULL, NULL);
|
||||||
|
|
||||||
float mindp = FLT_MAX, maxdp = -FLT_MAX;
|
float mindp = FLT_MAX, maxdp = -FLT_MAX;
|
||||||
for(uint32 i = 0 ; i < cluster.GetNumPoints(); i++) {
|
for(uint32 i = 0 ; i < cluster.GetNumPoints(); i++) {
|
||||||
float dp = (cluster.GetPoint(i) - avg) * axis;
|
float dp = (cluster.GetPoint(i) - cluster.GetAvg()) * axis;
|
||||||
if(dp < mindp) mindp = dp;
|
if(dp < mindp) mindp = dp;
|
||||||
if(dp > maxdp) maxdp = dp;
|
if(dp > maxdp) maxdp = dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
p1 = avg + mindp * axis;
|
p1 = cluster.GetAvg() + mindp * axis;
|
||||||
p2 = avg + maxdp * axis;
|
p2 = cluster.GetAvg() + maxdp * axis;
|
||||||
#else
|
#else
|
||||||
cluster.GetBoundingBox(p1, p2);
|
cluster.GetBoundingBox(p1, p2);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1447,7 +1387,7 @@ void CompressionMode::Pack(Params ¶ms, BitStream &stream) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
double CompressionMode::Compress(
|
double CompressionMode::Compress(
|
||||||
BitStream &stream, const int shapeIdx, const RGBACluster *clusters
|
BitStream &stream, const int shapeIdx, RGBACluster &cluster
|
||||||
) {
|
) {
|
||||||
|
|
||||||
const int kModeNumber = GetModeNumber();
|
const int kModeNumber = GetModeNumber();
|
||||||
|
@ -1458,6 +1398,7 @@ double CompressionMode::Compress(
|
||||||
double totalErr = 0.0;
|
double totalErr = 0.0;
|
||||||
for(int cidx = 0; cidx < nSubsets; cidx++) {
|
for(int cidx = 0; cidx < nSubsets; cidx++) {
|
||||||
uint8 indices[kMaxNumDataPoints] = {0};
|
uint8 indices[kMaxNumDataPoints] = {0};
|
||||||
|
cluster.SetPartition(cidx);
|
||||||
|
|
||||||
if(m_Attributes->hasRotation) {
|
if(m_Attributes->hasRotation) {
|
||||||
|
|
||||||
|
@ -1477,7 +1418,7 @@ double CompressionMode::Compress(
|
||||||
|
|
||||||
RGBAVector v1, v2;
|
RGBAVector v1, v2;
|
||||||
double error = CompressCluster(
|
double error = CompressCluster(
|
||||||
clusters[cidx], v1, v2, indices, alphaIndices
|
cluster, v1, v2, indices, alphaIndices
|
||||||
);
|
);
|
||||||
|
|
||||||
if(error < bestError) {
|
if(error < bestError) {
|
||||||
|
@ -1499,7 +1440,7 @@ double CompressionMode::Compress(
|
||||||
} else { // ! m_Attributes->hasRotation
|
} else { // ! m_Attributes->hasRotation
|
||||||
// Compress this cluster
|
// Compress this cluster
|
||||||
totalErr += CompressCluster(
|
totalErr += CompressCluster(
|
||||||
clusters[cidx],
|
cluster,
|
||||||
params.m_P1[cidx], params.m_P2[cidx],
|
params.m_P1[cidx], params.m_P2[cidx],
|
||||||
indices, params.m_PbitCombo[cidx]
|
indices, params.m_PbitCombo[cidx]
|
||||||
);
|
);
|
||||||
|
@ -1789,63 +1730,6 @@ void CompressAtomic(FasTC::CompressionJobList &cjl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PopulateTwoClustersForShape(
|
|
||||||
const uint32 points[16], int shapeIdx, RGBACluster *clusters
|
|
||||||
) {
|
|
||||||
clusters[0].Reset();
|
|
||||||
clusters[1].Reset();
|
|
||||||
const uint16 shape = kShapeMask2[shapeIdx];
|
|
||||||
for(uint32 pt = 0; pt < kMaxNumDataPoints; pt++) {
|
|
||||||
|
|
||||||
const RGBAVector p = RGBAVector(pt, points[pt]);
|
|
||||||
|
|
||||||
if((1 << pt) & shape)
|
|
||||||
clusters[1].AddPoint(p);
|
|
||||||
else
|
|
||||||
clusters[0].AddPoint(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
const uint32 pbs1 = clusters[0].GetPointBitString();
|
|
||||||
const uint32 pbs2 = clusters[1].GetPointBitString();
|
|
||||||
assert(!(pbs1 & pbs2));
|
|
||||||
assert((pbs1 ^ pbs2) == 0xFFFF);
|
|
||||||
assert((shape & pbs2) == shape);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PopulateThreeClustersForShape(
|
|
||||||
const uint32 points[16], int shapeIdx, RGBACluster *clusters
|
|
||||||
) {
|
|
||||||
clusters[0].Reset();
|
|
||||||
clusters[1].Reset();
|
|
||||||
clusters[2].Reset();
|
|
||||||
for(uint32 pt = 0; pt < kMaxNumDataPoints; pt++) {
|
|
||||||
|
|
||||||
const RGBAVector p = RGBAVector(pt, points[pt]);
|
|
||||||
|
|
||||||
if((1 << pt) & kShapeMask3[shapeIdx][0]) {
|
|
||||||
if((1 << pt) & kShapeMask3[shapeIdx][1]) {
|
|
||||||
clusters[2].AddPoint(p);
|
|
||||||
} else {
|
|
||||||
clusters[1].AddPoint(p);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
clusters[0].AddPoint(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
const uint32 pbs1 = clusters[0].GetPointBitString();
|
|
||||||
const uint32 pbs2 = clusters[1].GetPointBitString();
|
|
||||||
const uint32 pbs3 = clusters[2].GetPointBitString();
|
|
||||||
|
|
||||||
assert(!(pbs1 & pbs2));
|
|
||||||
assert(!(pbs3 & pbs2));
|
|
||||||
assert(!(pbs3 & pbs1));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static double EstimateTwoClusterError(RGBACluster &c) {
|
static double EstimateTwoClusterError(RGBACluster &c) {
|
||||||
RGBAVector Min, Max, v;
|
RGBAVector Min, Max, v;
|
||||||
c.GetBoundingBox(Min, Max);
|
c.GetBoundingBox(Min, Max);
|
||||||
|
@ -1907,13 +1791,15 @@ static ShapeSelection BoxSelection(uint32 x, uint32 y,
|
||||||
double bestError[2] = { std::numeric_limits<double>::max(),
|
double bestError[2] = { std::numeric_limits<double>::max(),
|
||||||
std::numeric_limits<double>::max() };
|
std::numeric_limits<double>::max() };
|
||||||
|
|
||||||
|
RGBACluster cluster(pixels);
|
||||||
|
|
||||||
for(unsigned int i = 0; i < kNumShapes2; i++) {
|
for(unsigned int i = 0; i < kNumShapes2; i++) {
|
||||||
RGBACluster clusters[2];
|
cluster.SetShapeIndex(i, 2);
|
||||||
PopulateTwoClustersForShape(pixels, i, clusters);
|
|
||||||
|
|
||||||
double err = 0.0;
|
double err = 0.0;
|
||||||
for(int ci = 0; ci < 2; ci++) {
|
for(int ci = 0; ci < 2; ci++) {
|
||||||
err += EstimateTwoClusterError(clusters[ci]);
|
cluster.SetPartition(ci);
|
||||||
|
err += EstimateTwoClusterError(cluster);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(err < bestError[0]) {
|
if(err < bestError[0]) {
|
||||||
|
@ -1932,13 +1818,12 @@ static ShapeSelection BoxSelection(uint32 x, uint32 y,
|
||||||
// if the entire block is opaque.
|
// if the entire block is opaque.
|
||||||
if(opaque) {
|
if(opaque) {
|
||||||
for(unsigned int i = 0; i < kNumShapes3; i++) {
|
for(unsigned int i = 0; i < kNumShapes3; i++) {
|
||||||
|
cluster.SetShapeIndex(i, 3);
|
||||||
RGBACluster clusters[3];
|
|
||||||
PopulateThreeClustersForShape(pixels, i, clusters);
|
|
||||||
|
|
||||||
double err = 0.0;
|
double err = 0.0;
|
||||||
for(int ci = 0; ci < 3; ci++) {
|
for(int ci = 0; ci < 3; ci++) {
|
||||||
err += EstimateThreeClusterError(clusters[ci]);
|
cluster.SetPartition(ci);
|
||||||
|
err += EstimateThreeClusterError(cluster);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(err < bestError[1]) {
|
if(err < bestError[1]) {
|
||||||
|
@ -1969,15 +1854,11 @@ static ShapeSelection BoxSelection(uint32 x, uint32 y,
|
||||||
|
|
||||||
static void CompressClusters(ShapeSelection selection, const uint32 pixels[16],
|
static void CompressClusters(ShapeSelection selection, const uint32 pixels[16],
|
||||||
uint8 *outBuf, double *errors, int *modeChosen) {
|
uint8 *outBuf, double *errors, int *modeChosen) {
|
||||||
RGBACluster clusters[3];
|
RGBACluster cluster(pixels);
|
||||||
uint8 tmpBuf[16];
|
uint8 tmpBuf[16];
|
||||||
double bestError = std::numeric_limits<double>::max();
|
double bestError = std::numeric_limits<double>::max();
|
||||||
uint32 modes[8] = {0, 2, 1, 3, 7, 4, 5, 6};
|
uint32 modes[8] = {0, 2, 1, 3, 7, 4, 5, 6};
|
||||||
|
|
||||||
bool populatedThree = false;
|
|
||||||
bool populatedTwo = false;
|
|
||||||
bool populatedOne = false;
|
|
||||||
|
|
||||||
// Block mode zero only has four bits for the partition index,
|
// Block mode zero only has four bits for the partition index,
|
||||||
// so if the chosen three-partition shape is not within this range,
|
// so if the chosen three-partition shape is not within this range,
|
||||||
// then we shouldn't consider using this block mode...
|
// then we shouldn't consider using this block mode...
|
||||||
|
@ -1995,28 +1876,18 @@ static void CompressClusters(ShapeSelection selection, const uint32 pixels[16],
|
||||||
uint32 shape = 0;
|
uint32 shape = 0;
|
||||||
if(modeIdx < 2) {
|
if(modeIdx < 2) {
|
||||||
shape = selection.m_ThreeShapeIndex;
|
shape = selection.m_ThreeShapeIndex;
|
||||||
if(!populatedThree) {
|
|
||||||
PopulateThreeClustersForShape(pixels, shape, clusters);
|
|
||||||
populatedThree = true;
|
|
||||||
}
|
|
||||||
} else if(modeIdx < 5) {
|
} else if(modeIdx < 5) {
|
||||||
shape = selection.m_TwoShapeIndex;
|
shape = selection.m_TwoShapeIndex;
|
||||||
if(!populatedTwo) {
|
|
||||||
PopulateTwoClustersForShape(pixels, shape, clusters);
|
|
||||||
populatedTwo = true;
|
|
||||||
}
|
|
||||||
} else if(!populatedOne) {
|
|
||||||
clusters[0].Reset();
|
|
||||||
for(uint32 i = 0; i < 16; i++) {
|
|
||||||
clusters[0].AddPoint(RGBAVector(i, pixels[i]));
|
|
||||||
}
|
|
||||||
populatedOne = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BitStream tmpStream(tmpBuf, 128, 0);
|
cluster.SetShapeIndex(
|
||||||
double error = CompressionMode(mode).Compress(tmpStream, shape, clusters);
|
shape, CompressionMode::GetAttributesForMode(mode)->numSubsets);
|
||||||
|
|
||||||
if(errors) errors[mode] = error;
|
BitStream tmpStream(tmpBuf, 128, 0);
|
||||||
|
double error = CompressionMode(mode).Compress(tmpStream, shape, cluster);
|
||||||
|
|
||||||
|
if(errors)
|
||||||
|
errors[mode] = error;
|
||||||
if(error < bestError) {
|
if(error < bestError) {
|
||||||
memcpy(outBuf, tmpBuf, sizeof(tmpBuf));
|
memcpy(outBuf, tmpBuf, sizeof(tmpBuf));
|
||||||
bestError = error;
|
bestError = error;
|
||||||
|
@ -2035,14 +1906,15 @@ static void CompressBC7Block(const uint32 block[16], uint8 *outBuf,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RGBACluster blockCluster;
|
RGBACluster blockCluster(block);
|
||||||
bool transparent = true;
|
bool transparent = true;
|
||||||
|
|
||||||
for(uint32 i = 0; i < kMaxNumDataPoints; i++) {
|
for(uint32 i = 0; i < blockCluster.GetNumPoints(); i++) {
|
||||||
RGBAVector p = RGBAVector(i, block[i]);
|
const RGBAVector &p = blockCluster.GetPoint(i);
|
||||||
blockCluster.AddPoint(p);
|
if(p.A() > 0.0f) {
|
||||||
if(p.A() > 0.0f)
|
|
||||||
transparent = false;
|
transparent = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The whole block is transparent?
|
// The whole block is transparent?
|
||||||
|
@ -2222,13 +2094,12 @@ static void CompressBC7Block(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RGBACluster blockCluster;
|
RGBACluster blockCluster(block);
|
||||||
bool opaque = true;
|
bool opaque = true;
|
||||||
bool transparent = true;
|
bool transparent = true;
|
||||||
|
|
||||||
for(uint32 i = 0; i < kMaxNumDataPoints; i++) {
|
for(uint32 i = 0; i < blockCluster.GetNumPoints(); i++) {
|
||||||
RGBAVector p = RGBAVector(i, block[i]);
|
const RGBAVector &p = blockCluster.GetPoint(i);
|
||||||
blockCluster.AddPoint(p);
|
|
||||||
if(fabs(p.A() - 255.0f) > 1e-10) {
|
if(fabs(p.A() - 255.0f) > 1e-10) {
|
||||||
opaque = false;
|
opaque = false;
|
||||||
}
|
}
|
||||||
|
@ -2273,14 +2144,14 @@ static void CompressBC7Block(
|
||||||
uint32 path = 0;
|
uint32 path = 0;
|
||||||
|
|
||||||
for(unsigned int i = 0; i < kNumShapes2; i++) {
|
for(unsigned int i = 0; i < kNumShapes2; i++) {
|
||||||
RGBACluster clusters[2];
|
blockCluster.SetShapeIndex(i, 2);
|
||||||
PopulateTwoClustersForShape(block, i, clusters);
|
|
||||||
|
|
||||||
double err = 0.0;
|
double err = 0.0;
|
||||||
double errEstimate[2] = { -1.0, -1.0 };
|
double errEstimate[2] = { -1.0, -1.0 };
|
||||||
for(int ci = 0; ci < 2; ci++) {
|
for(int ci = 0; ci < 2; ci++) {
|
||||||
|
blockCluster.SetPartition(ci);
|
||||||
double shapeEstimate[2] = { -1.0, -1.0 };
|
double shapeEstimate[2] = { -1.0, -1.0 };
|
||||||
err += EstimateTwoClusterErrorStats(clusters[ci], shapeEstimate);
|
err += EstimateTwoClusterErrorStats(blockCluster, shapeEstimate);
|
||||||
|
|
||||||
for(int ei = 0; ei < 2; ei++) {
|
for(int ei = 0; ei < 2; ei++) {
|
||||||
if(shapeEstimate[ei] >= 0.0) {
|
if(shapeEstimate[ei] >= 0.0) {
|
||||||
|
@ -2325,15 +2196,14 @@ static void CompressBC7Block(
|
||||||
// if the entire block is opaque.
|
// if the entire block is opaque.
|
||||||
if(opaque) {
|
if(opaque) {
|
||||||
for(unsigned int i = 0; i < kNumShapes3; i++) {
|
for(unsigned int i = 0; i < kNumShapes3; i++) {
|
||||||
|
blockCluster.SetShapeIndex(i, 3);
|
||||||
RGBACluster clusters[3];
|
|
||||||
PopulateThreeClustersForShape(block, i, clusters);
|
|
||||||
|
|
||||||
double err = 0.0;
|
double err = 0.0;
|
||||||
double errEstimate[2] = { -1.0, -1.0 };
|
double errEstimate[2] = { -1.0, -1.0 };
|
||||||
for(int ci = 0; ci < 3; ci++) {
|
for(int ci = 0; ci < 3; ci++) {
|
||||||
|
blockCluster.SetPartition(ci);
|
||||||
double shapeEstimate[2] = { -1.0, -1.0 };
|
double shapeEstimate[2] = { -1.0, -1.0 };
|
||||||
err += EstimateThreeClusterErrorStats(clusters[ci], shapeEstimate);
|
err += EstimateThreeClusterErrorStats(blockCluster, shapeEstimate);
|
||||||
|
|
||||||
for(int ei = 0; ei < 2; ei++) {
|
for(int ei = 0; ei < 2; ei++) {
|
||||||
if(shapeEstimate[ei] >= 0.0) {
|
if(shapeEstimate[ei] >= 0.0) {
|
||||||
|
|
|
@ -253,26 +253,6 @@ uint32 RGBAVector::ToPixel(const uint32 channelMask, const int pBit) const {
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
RGBACluster::RGBACluster(const RGBACluster &left, const RGBACluster &right) {
|
|
||||||
*this = left;
|
|
||||||
for(uint32 i = 0; i < right.m_NumPoints; i++) {
|
|
||||||
const RGBAVector &p = right.m_DataPoints[i];
|
|
||||||
AddPoint(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RGBACluster::AddPoint(const RGBAVector &p) {
|
|
||||||
assert(m_NumPoints < kMaxNumDataPoints);
|
|
||||||
m_Total += p;
|
|
||||||
m_DataPoints[m_NumPoints++] = p;
|
|
||||||
m_PointBitString |= 1 << p.GetIdx();
|
|
||||||
|
|
||||||
for(uint32 i = 0; i < kNumColorChannels; i++) {
|
|
||||||
m_Min[i] = min(p[i], m_Min[i]);
|
|
||||||
m_Max[i] = max(p[i], m_Max[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double RGBACluster::QuantizedError(
|
double RGBACluster::QuantizedError(
|
||||||
const RGBAVector &p1, const RGBAVector &p2,
|
const RGBAVector &p1, const RGBAVector &p2,
|
||||||
uint8 nBuckets, uint32 bitMask, const RGBAVector &errorMetricVec,
|
uint8 nBuckets, uint32 bitMask, const RGBAVector &errorMetricVec,
|
||||||
|
@ -308,9 +288,9 @@ double RGBACluster::QuantizedError(
|
||||||
const RGBAVector metric = errorMetricVec;
|
const RGBAVector metric = errorMetricVec;
|
||||||
|
|
||||||
float totalError = 0.0;
|
float totalError = 0.0;
|
||||||
for(uint32 i = 0; i < m_NumPoints; i++) {
|
for(uint32 i = 0; i < GetNumPoints(); i++) {
|
||||||
|
|
||||||
const uint32 pixel = m_DataPoints[i].ToPixel();
|
const uint32 pixel = GetPoint(i).ToPixel();
|
||||||
const uint8 *pb = (const uint8 *)(&pixel);
|
const uint8 *pb = (const uint8 *)(&pixel);
|
||||||
|
|
||||||
float minError = FLT_MAX;
|
float minError = FLT_MAX;
|
||||||
|
@ -351,34 +331,13 @@ double RGBACluster::QuantizedError(
|
||||||
return totalError;
|
return totalError;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
uint32 RGBACluster::GetPrincipalAxis(RGBADir &axis, float *eigOne, float *eigTwo) const {
|
||||||
//
|
|
||||||
// Utility function implementation
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void ClampEndpoints(RGBAVector &p1, RGBAVector &p2) {
|
|
||||||
for(uint32 i = 0; i < 4; i++) {
|
|
||||||
clamp(p1[i], 0.0f, 255.0f);
|
|
||||||
clamp(p2[i], 0.0f, 255.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 GetPrincipalAxis(uint32 nPts, const RGBAVector *pts, RGBADir &axis, float *eigOne, float *eigTwo) {
|
|
||||||
|
|
||||||
assert(nPts <= kMaxNumDataPoints);
|
|
||||||
|
|
||||||
RGBAVector avg (0.0f);
|
|
||||||
for(uint32 i = 0; i < nPts; i++) {
|
|
||||||
avg += pts[i];
|
|
||||||
}
|
|
||||||
avg /= float(nPts);
|
|
||||||
|
|
||||||
// We use these vectors for calculating the covariance matrix...
|
// We use these vectors for calculating the covariance matrix...
|
||||||
RGBAVector toPts[kMaxNumDataPoints];
|
RGBAVector toPts[kMaxNumDataPoints];
|
||||||
RGBAVector toPtsMax(-FLT_MAX);
|
RGBAVector toPtsMax(-std::numeric_limits<float>::max());
|
||||||
for(uint32 i = 0; i < nPts; i++) {
|
for(uint32 i = 0; i < this->GetNumPoints(); i++) {
|
||||||
toPts[i] = pts[i] - avg;
|
toPts[i] = this->GetPoint(i) - this->GetAvg();
|
||||||
|
|
||||||
for(uint32 j = 0; j < kNumColorChannels; j++) {
|
for(uint32 j = 0; j < kNumColorChannels; j++) {
|
||||||
toPtsMax[j] = max(toPtsMax[j], toPts[i][j]);
|
toPtsMax[j] = max(toPtsMax[j], toPts[i][j]);
|
||||||
|
@ -388,16 +347,16 @@ uint32 GetPrincipalAxis(uint32 nPts, const RGBAVector *pts, RGBADir &axis, float
|
||||||
// Generate a list of unique points...
|
// Generate a list of unique points...
|
||||||
RGBAVector upts[kMaxNumDataPoints];
|
RGBAVector upts[kMaxNumDataPoints];
|
||||||
uint32 uptsIdx = 0;
|
uint32 uptsIdx = 0;
|
||||||
for(uint32 i = 0; i < nPts; i++) {
|
for(uint32 i = 0; i < this->GetNumPoints(); i++) {
|
||||||
|
|
||||||
bool hasPt = false;
|
bool hasPt = false;
|
||||||
for(uint32 j = 0; j < uptsIdx; j++) {
|
for(uint32 j = 0; j < uptsIdx; j++) {
|
||||||
if(upts[j] == pts[i])
|
if(upts[j] == this->GetPoint(i))
|
||||||
hasPt = true;
|
hasPt = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!hasPt) {
|
if(!hasPt) {
|
||||||
upts[uptsIdx++] = pts[i];
|
upts[uptsIdx++] = this->GetPoint(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +370,7 @@ uint32 GetPrincipalAxis(uint32 nPts, const RGBAVector *pts, RGBADir &axis, float
|
||||||
} else {
|
} else {
|
||||||
RGBADir dir (upts[1] - upts[0]);
|
RGBADir dir (upts[1] - upts[0]);
|
||||||
bool collinear = true;
|
bool collinear = true;
|
||||||
for(uint32 i = 2; i < nPts; i++) {
|
for(uint32 i = 2; i < this->GetNumPoints(); i++) {
|
||||||
RGBAVector v = (upts[i] - upts[0]);
|
RGBAVector v = (upts[i] - upts[0]);
|
||||||
if(fabs(fabs(v*dir) - v.Length()) > 1e-7) {
|
if(fabs(fabs(v*dir) - v.Length()) > 1e-7) {
|
||||||
collinear = false;
|
collinear = false;
|
||||||
|
@ -432,7 +391,7 @@ uint32 GetPrincipalAxis(uint32 nPts, const RGBAVector *pts, RGBADir &axis, float
|
||||||
for(uint32 j = 0; j <= i; j++) {
|
for(uint32 j = 0; j <= i; j++) {
|
||||||
|
|
||||||
float sum = 0.0;
|
float sum = 0.0;
|
||||||
for(uint32 k = 0; k < nPts; k++) {
|
for(uint32 k = 0; k < this->GetNumPoints(); k++) {
|
||||||
sum += toPts[k][i] * toPts[k][j];
|
sum += toPts[k][i] * toPts[k][j];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,3 +433,16 @@ uint32 GetPrincipalAxis(uint32 nPts, const RGBAVector *pts, RGBADir &axis, float
|
||||||
|
|
||||||
return iters;
|
return iters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Utility function implementation
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void ClampEndpoints(RGBAVector &p1, RGBAVector &p2) {
|
||||||
|
for(uint32 i = 0; i < 4; i++) {
|
||||||
|
clamp(p1[i], 0.0f, 255.0f);
|
||||||
|
clamp(p2[i], 0.0f, 255.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -70,9 +70,13 @@
|
||||||
#include "Vector4.h"
|
#include "Vector4.h"
|
||||||
#include "Matrix4x4.h"
|
#include "Matrix4x4.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include "Shapes.h"
|
||||||
|
|
||||||
static const uint32 kNumColorChannels = 4;
|
static const uint32 kNumColorChannels = 4;
|
||||||
static const uint32 kMaxNumDataPoints = 16;
|
static const uint32 kMaxNumDataPoints = 16;
|
||||||
|
@ -122,45 +126,37 @@ class RGBADir : public RGBAVector {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Makes sure that the values of the endpoints lie between 0 and 1.
|
|
||||||
extern void ClampEndpoints(RGBAVector &p1, RGBAVector &p2);
|
|
||||||
|
|
||||||
class RGBACluster {
|
class RGBACluster {
|
||||||
|
// We really don't ever need to do these
|
||||||
|
RGBACluster &operator=(const RGBACluster &) { return *this; }
|
||||||
public:
|
public:
|
||||||
|
explicit RGBACluster(const uint32 pixels[16])
|
||||||
|
: m_NumPoints(0)
|
||||||
|
, m_Avg(0)
|
||||||
|
, m_Min(std::numeric_limits<float>::max())
|
||||||
|
, m_Max(-std::numeric_limits<float>::max())
|
||||||
|
{
|
||||||
|
for(uint32 i = 0; i < 16; i++) {
|
||||||
|
RGBAVector p = RGBAVector(i, pixels[i]);
|
||||||
|
m_Avg += p;
|
||||||
|
m_PointMap[m_NumPoints] = i;
|
||||||
|
m_DataPoints[m_NumPoints++] = p;
|
||||||
|
|
||||||
RGBACluster() :
|
for(uint32 i = 0; i < kNumColorChannels; i++) {
|
||||||
m_NumPoints(0), m_Total(0),
|
m_Min[i] = std::min(p[i], m_Min[i]);
|
||||||
m_PointBitString(0),
|
m_Max[i] = std::max(p[i], m_Max[i]);
|
||||||
m_Min(FLT_MAX),
|
}
|
||||||
m_Max(-FLT_MAX)
|
}
|
||||||
{ }
|
m_Avg /= static_cast<float>(m_NumPoints);
|
||||||
|
|
||||||
RGBACluster(const RGBACluster &c) :
|
|
||||||
m_NumPoints(c.m_NumPoints),
|
|
||||||
m_Total(c.m_Total),
|
|
||||||
m_PointBitString(c.m_PointBitString),
|
|
||||||
m_Min(c.m_Min), m_Max(c.m_Max)
|
|
||||||
{
|
|
||||||
memcpy(this->m_DataPoints, c.m_DataPoints, m_NumPoints * sizeof(RGBAVector));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RGBACluster(const RGBACluster &left, const RGBACluster &right);
|
RGBAVector &Point(int idx) { return m_DataPoints[m_PointMap[idx]]; }
|
||||||
RGBACluster(const RGBAVector &p) :
|
const RGBAVector &GetPoint(int idx) const {
|
||||||
m_NumPoints(1),
|
return m_DataPoints[m_PointMap[idx]];
|
||||||
m_Total(p),
|
|
||||||
m_PointBitString(0),
|
|
||||||
m_Min(p), m_Max(p)
|
|
||||||
{
|
|
||||||
m_DataPoints[0] = p;
|
|
||||||
m_PointBitString |= (1 << p.GetIdx());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const RGBAVector &GetPoint(int idx) const { return m_DataPoints[idx]; }
|
|
||||||
uint32 GetNumPoints() const { return m_NumPoints; }
|
uint32 GetNumPoints() const { return m_NumPoints; }
|
||||||
RGBAVector GetAvg() const { return m_Total / float(m_NumPoints); }
|
RGBAVector GetAvg() const { return m_Avg; }
|
||||||
const RGBAVector *GetPoints() const { return m_DataPoints; }
|
|
||||||
|
|
||||||
void AddPoint(const RGBAVector &p);
|
|
||||||
|
|
||||||
void GetBoundingBox(RGBAVector &Min, RGBAVector &Max) const {
|
void GetBoundingBox(RGBAVector &Min, RGBAVector &Max) const {
|
||||||
Min = m_Min, Max = m_Max;
|
Min = m_Min, Max = m_Max;
|
||||||
|
@ -173,27 +169,72 @@ public:
|
||||||
uint8 nBuckets, uint32 bitMask, const RGBAVector &errorMetricVec,
|
uint8 nBuckets, uint32 bitMask, const RGBAVector &errorMetricVec,
|
||||||
const int pbits[2] = NULL, uint8 *indices = NULL) const;
|
const int pbits[2] = NULL, uint8 *indices = NULL) const;
|
||||||
|
|
||||||
// Returns the principal axis for this point cluster.
|
|
||||||
bool AllSamePoint() const { return m_Max == m_Min; }
|
bool AllSamePoint() const { return m_Max == m_Min; }
|
||||||
int GetPointBitString() const { return m_PointBitString; }
|
|
||||||
|
|
||||||
void Reset() { *this = RGBACluster(); }
|
// Returns the principal axis for this point cluster.
|
||||||
|
uint32 GetPrincipalAxis(RGBADir &axis, float *eigOne, float *eigTwo) const;
|
||||||
|
|
||||||
|
void SetShapeIndex(uint32 shapeIdx, uint32 nPartitions) {
|
||||||
|
m_NumPartitions = nPartitions;
|
||||||
|
m_ShapeIdx = shapeIdx;
|
||||||
|
// Recalculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetShapeIndex(uint32 shapeIdx) {
|
||||||
|
SetShapeIndex(shapeIdx, m_NumPartitions);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPartition(uint32 part) {
|
||||||
|
m_SelectedPartition = part;
|
||||||
|
Recalculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsPointValid(uint32 idx) const {
|
||||||
|
return m_SelectedPartition ==
|
||||||
|
BPTCC::GetSubsetForIndex(idx, m_ShapeIdx, m_NumPartitions);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The number of points in the cluster.
|
// The number of points in the cluster.
|
||||||
uint32 m_NumPoints;
|
uint32 m_NumPoints;
|
||||||
|
uint32 m_NumPartitions;
|
||||||
|
uint32 m_SelectedPartition;
|
||||||
|
uint32 m_ShapeIdx;
|
||||||
|
|
||||||
RGBAVector m_Total;
|
RGBAVector m_Avg;
|
||||||
|
|
||||||
// The points in the cluster.
|
// The points in the cluster.
|
||||||
RGBAVector m_DataPoints[kMaxNumDataPoints];
|
RGBAVector m_DataPoints[kMaxNumDataPoints];
|
||||||
|
uint8 m_PointMap[kMaxNumDataPoints];
|
||||||
int m_PointBitString;
|
|
||||||
RGBAVector m_Min, m_Max;
|
RGBAVector m_Min, m_Max;
|
||||||
|
|
||||||
|
void Recalculate() {
|
||||||
|
m_NumPoints = 0;
|
||||||
|
m_Avg = RGBAVector(0.0f);
|
||||||
|
m_Min = RGBAVector(std::numeric_limits<float>::max());
|
||||||
|
m_Max = RGBAVector(-std::numeric_limits<float>::max());
|
||||||
|
|
||||||
|
uint32 map = 0;
|
||||||
|
for(uint32 idx = 0; idx < 16; idx++) {
|
||||||
|
if(!IsPointValid(idx)) continue;
|
||||||
|
|
||||||
|
m_NumPoints++;
|
||||||
|
m_Avg += m_DataPoints[idx];
|
||||||
|
m_PointMap[map++] = idx;
|
||||||
|
|
||||||
|
for(uint32 i = 0; i < kNumColorChannels; i++) {
|
||||||
|
m_Min[i] = std::min(m_DataPoints[idx][i], m_Min[i]);
|
||||||
|
m_Max[i] = std::max(m_DataPoints[idx][i], m_Max[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Avg /= static_cast<float>(m_NumPoints);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Makes sure that the values of the endpoints lie between 0 and 1.
|
||||||
|
extern void ClampEndpoints(RGBAVector &p1, RGBAVector &p2);
|
||||||
extern uint8 QuantizeChannel(const uint8 val, const uint8 mask, const int pBit = -1);
|
extern uint8 QuantizeChannel(const uint8 val, const uint8 mask, const int pBit = -1);
|
||||||
extern uint32 GetPrincipalAxis(uint32 nPts, const RGBAVector *pts, RGBADir &axis, float *eigOne, float *eigTwo);
|
|
||||||
|
|
||||||
namespace FasTC {
|
namespace FasTC {
|
||||||
REGISTER_VECTOR_TYPE(RGBAVector);
|
REGISTER_VECTOR_TYPE(RGBAVector);
|
||||||
|
|
118
BPTCEncoder/src/Shapes.h
Normal file
118
BPTCEncoder/src/Shapes.h
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/* FasTC
|
||||||
|
* Copyright (c) 2013 University of North Carolina at Chapel Hill.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software and its
|
||||||
|
* documentation for educational, research, and non-profit purposes, without
|
||||||
|
* fee, and without a written agreement is hereby granted, provided that the
|
||||||
|
* above copyright notice, this paragraph, and the following four paragraphs
|
||||||
|
* appear in all copies.
|
||||||
|
*
|
||||||
|
* Permission to incorporate this software into commercial products may be
|
||||||
|
* obtained by contacting the authors or the Office of Technology Development
|
||||||
|
* at the University of North Carolina at Chapel Hill <otd@unc.edu>.
|
||||||
|
*
|
||||||
|
* This software program and documentation are copyrighted by the University of
|
||||||
|
* North Carolina at Chapel Hill. The software program and documentation are
|
||||||
|
* supplied "as is," without any accompanying services from the University of
|
||||||
|
* North Carolina at Chapel Hill or the authors. The University of North
|
||||||
|
* Carolina at Chapel Hill and the authors do not warrant that the operation of
|
||||||
|
* the program will be uninterrupted or error-free. The end-user understands
|
||||||
|
* that the program was developed for research purposes and is advised not to
|
||||||
|
* rely exclusively on the program for any reason.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE
|
||||||
|
* AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
|
||||||
|
* OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA
|
||||||
|
* AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY
|
||||||
|
* DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY
|
||||||
|
* STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON
|
||||||
|
* AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND
|
||||||
|
* THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
||||||
|
* ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Please send all BUG REPORTS to <pavel@cs.unc.edu>.
|
||||||
|
*
|
||||||
|
* The authors may be contacted via:
|
||||||
|
*
|
||||||
|
* Pavel Krajcevski
|
||||||
|
* Dept of Computer Science
|
||||||
|
* 201 S Columbia St
|
||||||
|
* Frederick P. Brooks, Jr. Computer Science Bldg
|
||||||
|
* Chapel Hill, NC 27599-3175
|
||||||
|
* USA
|
||||||
|
*
|
||||||
|
* <http://gamma.cs.unc.edu/FasTC/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BPTCENCODER_SRC_SHAPES_H_
|
||||||
|
#define BPTCENCODER_SRC_SHAPES_H_
|
||||||
|
|
||||||
|
namespace BPTCC {
|
||||||
|
|
||||||
|
static const uint32 kNumShapes2 = 64;
|
||||||
|
static const uint16 kShapeMask2[kNumShapes2] = {
|
||||||
|
0xcccc, 0x8888, 0xeeee, 0xecc8, 0xc880, 0xfeec, 0xfec8, 0xec80,
|
||||||
|
0xc800, 0xffec, 0xfe80, 0xe800, 0xffe8, 0xff00, 0xfff0, 0xf000,
|
||||||
|
0xf710, 0x008e, 0x7100, 0x08ce, 0x008c, 0x7310, 0x3100, 0x8cce,
|
||||||
|
0x088c, 0x3110, 0x6666, 0x366c, 0x17e8, 0x0ff0, 0x718e, 0x399c,
|
||||||
|
0xaaaa, 0xf0f0, 0x5a5a, 0x33cc, 0x3c3c, 0x55aa, 0x9696, 0xa55a,
|
||||||
|
0x73ce, 0x13c8, 0x324c, 0x3bdc, 0x6996, 0xc33c, 0x9966, 0x0660,
|
||||||
|
0x0272, 0x04e4, 0x4e40, 0x2720, 0xc936, 0x936c, 0x39c6, 0x639c,
|
||||||
|
0x9336, 0x9cc6, 0x817e, 0xe718, 0xccf0, 0x0fcc, 0x7744, 0xee22
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint32 kNumShapes3 = 64;
|
||||||
|
static const uint16 kShapeMask3[kNumShapes3][2] = {
|
||||||
|
{0xfecc, 0xf600}, {0xffc8, 0x7300}, {0xff90, 0x3310}, {0xecce, 0x00ce},
|
||||||
|
{0xff00, 0xcc00}, {0xcccc, 0xcc00}, {0xffcc, 0x00cc}, {0xffcc, 0x3300},
|
||||||
|
{0xff00, 0xf000}, {0xfff0, 0xf000}, {0xfff0, 0xff00}, {0xcccc, 0x8888},
|
||||||
|
{0xeeee, 0x8888}, {0xeeee, 0xcccc}, {0xffec, 0xec80}, {0x739c, 0x7310},
|
||||||
|
{0xfec8, 0xc800}, {0x39ce, 0x3100}, {0xfff0, 0xccc0}, {0xfccc, 0x0ccc},
|
||||||
|
{0xeeee, 0xee00}, {0xff88, 0x7700}, {0xeec0, 0xcc00}, {0x7730, 0x3300},
|
||||||
|
{0x0cee, 0x00cc}, {0xffcc, 0xfc88}, {0x6ff6, 0x0660}, {0xff60, 0x6600},
|
||||||
|
{0xcbbc, 0xc88c}, {0xf966, 0xf900}, {0xceec, 0x0cc0}, {0xff10, 0x7310},
|
||||||
|
{0xff80, 0xec80}, {0xccce, 0x08ce}, {0xeccc, 0xec80}, {0x6666, 0x4444},
|
||||||
|
{0x0ff0, 0x0f00}, {0x6db6, 0x4924}, {0x6bd6, 0x4294}, {0xcf3c, 0x0c30},
|
||||||
|
{0xc3fc, 0x03c0}, {0xffaa, 0xff00}, {0xff00, 0x5500}, {0xfcfc, 0xcccc},
|
||||||
|
{0xcccc, 0x0c0c}, {0xf6f6, 0x6666}, {0xaffa, 0x0ff0}, {0xfff0, 0x5550},
|
||||||
|
{0xfaaa, 0xf000}, {0xeeee, 0x0e0e}, {0xf8f8, 0x8888}, {0xfff0, 0x9990},
|
||||||
|
{0xeeee, 0xe00e}, {0x8ff8, 0x8888}, {0xf666, 0xf000}, {0xff00, 0x9900},
|
||||||
|
{0xff66, 0xff00}, {0xcccc, 0xc00c}, {0xcffc, 0xcccc}, {0xf000, 0x9000},
|
||||||
|
{0x8888, 0x0808}, {0xfefe, 0xeeee}, {0xfffa, 0xfff0}, {0x7bde, 0x7310}
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8 GetSubsetForIndex(int idx, const int shapeIdx, const int nSubs) {
|
||||||
|
int subset = 0;
|
||||||
|
|
||||||
|
switch(nSubs) {
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
subset = !!((1 << idx) & kShapeMask2[shapeIdx]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
if(1 << idx & kShapeMask3[shapeIdx][0])
|
||||||
|
subset = 1 + !!((1 << idx) & kShapeMask3[shapeIdx][1]);
|
||||||
|
else
|
||||||
|
subset = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return subset;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace BPTCC
|
||||||
|
|
||||||
|
#endif // BPTCENCODER_SRC_SHAPES_H_
|
Loading…
Reference in a new issue