//=============================================================================== // Copyright (c) 2007-2016 Advanced Micro Devices, Inc. All rights reserved. // Copyright (c) 2004-2006 ATI Technologies Inc. //=============================================================================== // // 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. #ifndef _BC7_ENCODE_H_ #define _BC7_ENCODE_H_ #include #include "bc7_definitions.h" #include "debug.h" #include "cmp_core.h" #include // Threshold quality below which we will always run fast quality and shaking // Self note: User should be able to set this? extern double g_qFAST_THRESHOLD; extern double g_HIGHQULITY_THRESHOLD; class BC7BlockEncoder { public: BC7BlockEncoder(CMP_DWORD validModeMask, CMP_BOOL imageNeedsAlpha, double quality, CMP_BOOL colourRestrict, CMP_BOOL alphaRestrict, double performance = 1.0 ) { // Bug check : ModeMask must be > 0 if (validModeMask <= 0) m_validModeMask = 0xCF; else m_validModeMask = validModeMask; m_quality = cmp_minT(1.0, cmp_maxT(quality, 0.0)); m_performance = cmp_minT(1.0, cmp_maxT(performance, 0.0)); m_imageNeedsAlpha = imageNeedsAlpha; m_smallestError = DBL_MAX; m_largestError = 0.0; m_colourRestrict = colourRestrict; m_alphaRestrict = alphaRestrict; m_quantizerRangeThreshold = 255 * m_performance; if(m_quality < g_qFAST_THRESHOLD) { // Make sure this is below 0.5 since we are x2 below. m_shakerRangeThreshold = 0.; // Scale m_quality to be a linar range 0 to 1 in this section // to maximize quality with fast performance... m_errorThreshold = 256. * (1.0 - ((m_quality*2.0)/g_qFAST_THRESHOLD)); // Limit the size of the partition search space based on Quality m_partitionSearchSize = cmp_maxT( (1.0/16.0), ((m_quality*2.0) / g_qFAST_THRESHOLD)); } else { // m_qaulity = set the quality user want to see on encoding // higher values will produce better encoding results. // m_performance - sets a perfoamce level for a specified quality level if(m_quality < g_HIGHQULITY_THRESHOLD) { m_shakerRangeThreshold = 255 * (m_quality / 10); // gain performance within FAST_THRESHOLD and HIGHQULITY_THRESHOLD range m_errorThreshold = 256. * (1.0 - (m_quality/g_qFAST_THRESHOLD)); // Limit the size of the partition search space based on Quality m_partitionSearchSize = cmp_maxT( (1.0/16.0), (m_quality / g_qFAST_THRESHOLD)); } else { m_shakerRangeThreshold = 255 * m_quality; // lowers performance with incresing values m_errorThreshold = 0; // Dont exit early m_partitionSearchSize = 1.0; // use all partitions for best quality } } #ifdef USE_DBGTRACE DbgTrace(("shakerRangeThreshold [%3.3f] errorThreshold [%3.3f] partitionSearchSize [%3.3f]",m_shakerRangeThreshold,m_errorThreshold,m_partitionSearchSize)); #endif }; ~BC7BlockEncoder() { #ifdef USE_DBGTRACE DbgTrace(("Smallest Error %f", (float)m_smallestError)); DbgTrace(("Largest Error %f", (float)m_largestError)); #endif }; // This routine compresses a block and returns the RMS error double CompressBlock(double in[MAX_SUBSET_SIZE][MAX_DIMENSION_BIG], CMP_BYTE out[COMPRESSED_BLOCK_SIZE]); private: double quant_single_point_d( double data[MAX_ENTRIES][MAX_DIMENSION_BIG], int numEntries, int index[MAX_ENTRIES], double out[MAX_ENTRIES][MAX_DIMENSION_BIG], int epo_1[2][MAX_DIMENSION_BIG], int Mi_, // last cluster int bits[3], // including parity int type, int dimension ); double ep_shaker_2_d( double data[MAX_ENTRIES][MAX_DIMENSION_BIG], int numEntries, int index_[MAX_ENTRIES], double out[MAX_ENTRIES][MAX_DIMENSION_BIG], int epo_code[2][MAX_DIMENSION_BIG], int size, int Mi_, // last cluster int bits, // total for all channels // defined by total numbe of bits and dimensioin int dimension, double epo[2][MAX_DIMENSION_BIG] ); double ep_shaker_d( double data[MAX_ENTRIES][MAX_DIMENSION_BIG], int numEntries, int index_[MAX_ENTRIES], double out[MAX_ENTRIES][MAX_DIMENSION_BIG], int epo_code[2][MAX_DIMENSION_BIG], int Mi_, // last cluster int bits[3], // including parity CMP_qt_cpu type, int dimension ); void BlockSetup(CMP_DWORD blockMode); void EncodeSingleIndexBlock(CMP_DWORD blockMode, CMP_DWORD partition, CMP_DWORD colour[MAX_SUBSETS][2], int indices[MAX_SUBSETS][MAX_SUBSET_SIZE], CMP_BYTE block[COMPRESSED_BLOCK_SIZE]); // This routine compresses a block to any of the single index modes double CompressSingleIndexBlock(double in[MAX_SUBSET_SIZE][MAX_DIMENSION_BIG], CMP_BYTE out[COMPRESSED_BLOCK_SIZE], CMP_DWORD blockMode); void EncodeDualIndexBlock(CMP_DWORD blockMode, CMP_DWORD indexSelection, CMP_DWORD componentRotation, int endpoint[2][2][MAX_DIMENSION_BIG], int indices[2][MAX_SUBSET_SIZE], CMP_BYTE out[COMPRESSED_BLOCK_SIZE]); // This routine compresses a block to any of the dual index modes double CompressDualIndexBlock(double in[MAX_SUBSET_SIZE][MAX_DIMENSION_BIG], CMP_BYTE out[COMPRESSED_BLOCK_SIZE], CMP_DWORD blockMode); // Bulky temporary data used during compression of a block int m_storedIndices[MAX_PARTITIONS][MAX_SUBSETS][MAX_SUBSET_SIZE]; double m_storedError[MAX_PARTITIONS]; int m_sortedModes[MAX_PARTITIONS]; // This stores the min and max for the components of the block, and the ranges double m_blockMin[MAX_DIMENSION_BIG]; double m_blockMax[MAX_DIMENSION_BIG]; double m_blockRange[MAX_DIMENSION_BIG]; double m_blockMaxRange; // These are quality parameters used to select when to use the high precision quantizer // and shaker paths double m_quantizerRangeThreshold; double m_shakerRangeThreshold; double m_partitionSearchSize; // Global data setup at initialisation time double m_quality; double m_performance; double m_errorThreshold; CMP_DWORD m_validModeMask; CMP_BOOL m_imageNeedsAlpha; CMP_BOOL m_colourRestrict; CMP_BOOL m_alphaRestrict; // Data for compressing a particular block mode CMP_DWORD m_parityBits; CMP_DWORD m_clusters[2]; CMP_DWORD m_componentBits[MAX_DIMENSION_BIG]; // Error stats double m_smallestError; double m_largestError; }; #endif