@ -25,6 +25,7 @@
# include "BlockCompressor.h"
# include "OutputOptions.h"
# include "TaskDispatcher.h"
# include "CompressionOptions.h"
# include "nvimage/Image.h"
# include "nvimage/ColorBlock.h"
@ -33,6 +34,7 @@
# include "nvmath/Vector.inl"
# include "nvcore/Memory.h"
# include "nvcore/Array.inl"
# include <new> // placement new
@ -40,85 +42,13 @@
using namespace nv ;
using namespace nvtt ;
/*
// OpenMP
# if defined(HAVE_OPENMP)
# include <omp.h>
# endif
void ColorBlockCompressor : : compress ( nvtt : : AlphaMode alphaMode , uint w , uint h , const float * data , const nvtt : : CompressionOptions : : Private & compressionOptions , const nvtt : : OutputOptions : : Private & outputOptions )
{
const uint bs = blockSize ( ) ;
const uint bw = ( w + 3 ) / 4 ;
const uint bh = ( h + 3 ) / 4 ;
# if defined(HAVE_OPENMP)
bool singleThreaded = false ;
# else
bool singleThreaded = true ;
# endif
// Use a single thread to compress small textures.
if ( bw * bh < 16 ) singleThreaded = true ;
if ( singleThreaded )
{
nvDebugCheck ( bs < = 16 ) ;
uint8 mem [ 16 ] ; // @@ Output one row at a time!
for ( int y = 0 ; y < int ( h ) ; y + = 4 ) {
for ( uint x = 0 ; x < w ; x + = 4 ) {
ColorBlock rgba ;
rgba . init ( w , h , data , x , y ) ;
compressBlock ( rgba , alphaMode , compressionOptions , mem ) ;
if ( outputOptions . outputHandler ! = NULL ) {
outputOptions . outputHandler - > writeData ( mem , bs ) ;
}
}
}
}
# if defined(HAVE_OPENMP)
else
{
const uint size = bs * bw * bh ;
uint8 * mem = new uint8 [ size ] ;
# pragma omp parallel
{
# pragma omp for
for ( int i = 0 ; i < int ( bw * bh ) ; i + + )
{
const uint x = i % bw ;
const uint y = i / bw ;
ColorBlock rgba ;
rgba . init ( w , h , data , 4 * x , 4 * y ) ;
uint8 * ptr = mem + ( y * bw + x ) * bs ;
compressBlock ( rgba , alphaMode , compressionOptions , ptr ) ;
} // omp for
} // omp parallel
if ( outputOptions . outputHandler ! = NULL ) {
outputOptions . outputHandler - > writeData ( mem , size ) ;
}
delete [ ] mem ;
}
# endif
}
*/
struct CompressorContext
{
nvtt: : AlphaMode alphaMode ;
AlphaMode alphaMode ;
uint w , h , d ;
const float * data ;
const nvtt: : CompressionOptions: : Private * compressionOptions ;
const CompressionOptions : : Private * compressionOptions ;
uint bw , bh , bs ;
uint8 * mem ;
@ -144,7 +74,7 @@ void ColorBlockCompressorTask(void * data, int i)
}
}
void ColorBlockCompressor : : compress ( nvtt: : AlphaMode alphaMode , uint w , uint h , uint d , const float * data , nvtt : : TaskDispatcher * dispatcher , const nvtt: : CompressionOptions: : Private & compressionOptions , const nvtt : : OutputOptions : : Private & outputOptions )
void ColorBlockCompressor : : compress ( AlphaMode alphaMode , uint w , uint h , uint d , const float * data , TaskDispatcher * dispatcher , const CompressionOptions: : Private & compressionOptions , const OutputOptions : : Private & outputOptions )
{
nvDebugCheck ( d = = 1 ) ;
@ -182,66 +112,6 @@ void ColorBlockCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, u
delete [ ] context . mem ;
}
#if 0
// Each task compresses one block.
void ColorSetCompressorTask ( void * data , int i )
{
CompressorContext * d = ( CompressorContext * ) data ;
uint x = i % d - > bw ;
uint y = i / d - > bw ;
//for (uint x = 0; x < d->bw; x++)
{
ColorSet set ;
set . setColors ( d - > data , d - > w , d - > h , x * 4 , y * 4 ) ;
uint8 * ptr = d - > mem + ( y * d - > bw + x ) * d - > bs ;
( ( ColorSetCompressor * ) d - > compressor ) - > compressBlock ( set , d - > alphaMode , * d - > compressionOptions , ptr ) ;
}
}
void ColorSetCompressor : : compress ( AlphaMode alphaMode , uint w , uint h , uint d , const float * data , nvtt : : TaskDispatcher * dispatcher , const CompressionOptions : : Private & compressionOptions , const OutputOptions : : Private & outputOptions )
{
nvDebugCheck ( d = = 1 ) ;
CompressorContext context ;
context . alphaMode = alphaMode ;
context . w = w ;
context . h = h ;
context . data = data ;
context . compressionOptions = & compressionOptions ;
context . bs = blockSize ( ) ;
context . bw = ( w + 3 ) / 4 ;
context . bh = ( h + 3 ) / 4 ;
context . compressor = this ;
SequentialTaskDispatcher sequential ;
// Use a single thread to compress small textures.
if ( context . bh < 4 ) dispatcher = & sequential ;
# if _DEBUG
dispatcher = & sequential ;
# endif
const uint count = context . bw * context . bh ;
const uint size = context . bs * count ;
context . mem = new uint8 [ size ] ;
dispatcher - > dispatch ( ColorSetCompressorTask , & context , count ) ;
outputOptions . writeData ( context . mem , size ) ;
delete [ ] context . mem ;
}
# endif // 0
// Each task compresses one block.
void FloatColorCompressorTask ( void * data , int i )
{
@ -262,8 +132,8 @@ void FloatColorCompressorTask(void * data, int i)
Vector4 colors [ 16 ] ;
float weights [ 16 ] ;
const uint block_w = min ( d - > w - block_x * 4 U , 4U ) ;
const uint block_h = min ( d - > h - block_y * 4 U , 4U ) ;
const uint block_w = min ( d - > w - block_x * 4 , 4U ) ;
const uint block_h = min ( d - > h - block_y * 4 , 4U ) ;
uint x , y ;
for ( y = 0 ; y < block_h ; y + + ) {
@ -274,7 +144,7 @@ void FloatColorCompressorTask(void * data, int i)
colors [ dst_idx ] . y = g [ src_idx ] ;
colors [ dst_idx ] . z = b [ src_idx ] ;
colors [ dst_idx ] . w = a [ src_idx ] ;
weights [ dst_idx ] = ( d - > alphaMode = = nvtt: : AlphaMode_Transparency) ? a[ src_idx ] : 1.0f ;
weights [ dst_idx ] = ( d - > alphaMode = = AlphaMode_Transparency) ? saturate( a[ src_idx ] ) : 1.0f ;
}
for ( ; x < 4 ; x + + ) {
uint dst_idx = 4 * y + x ;
@ -296,7 +166,7 @@ void FloatColorCompressorTask(void * data, int i)
}
void FloatColorCompressor : : compress ( AlphaMode alphaMode , uint w , uint h , uint d , const float * data , nvtt: : TaskDispatcher * dispatcher , const CompressionOptions : : Private & compressionOptions , const OutputOptions : : Private & outputOptions )
void FloatColorCompressor : : compress ( AlphaMode alphaMode , uint w , uint h , uint d , const float * data , TaskDispatcher * dispatcher , const CompressionOptions : : Private & compressionOptions , const OutputOptions : : Private & outputOptions )
{
nvDebugCheck ( d = = 1 ) ; // @@ Add support for compressed 3D textures.
@ -308,7 +178,7 @@ void FloatColorCompressor::compress(AlphaMode alphaMode, uint w, uint h, uint d,
context . data = data ;
context . compressionOptions = & compressionOptions ;
context . bs = blockSize ( ) ;
context . bs = blockSize ( compressionOptions ) ;
context . bw = ( w + 3 ) / 4 ;
context . bh = ( h + 3 ) / 4 ;
@ -333,3 +203,466 @@ void FloatColorCompressor::compress(AlphaMode alphaMode, uint w, uint h, uint d,
delete [ ] context . mem ;
}
// BC1
# include "CompressorDXT1.h"
void FastCompressorDXT1 : : compressBlock ( Vector4 colors [ 16 ] , float weights [ 16 ] , const CompressionOptions : : Private & compressionOptions , void * output )
{
compress_dxt1_fast ( colors , weights , compressionOptions . colorWeight . xyz ( ) , ( BlockDXT1 * ) output ) ;
}
void CompressorDXT1 : : compressBlock ( Vector4 colors [ 16 ] , float weights [ 16 ] , const CompressionOptions : : Private & compressionOptions , void * output )
{
compress_dxt1 ( colors , weights , compressionOptions . colorWeight . xyz ( ) , /*three_color_mode*/ true , ( BlockDXT1 * ) output ) ;
}
// @@ BC1a
// @@ BC2
// @@ BC3
// BC3_RGBM
# include "CompressorDXT5_RGBM.h"
void CompressorBC3_RGBM : : compressBlock ( Vector4 colors [ 16 ] , float weights [ 16 ] , const CompressionOptions : : Private & compressionOptions , void * output )
{
compress_dxt5_rgbm ( colors , weights , compressionOptions . rgbmThreshold , ( BlockDXT5 * ) output ) ;
}
// ETC
# include "CompressorETC.h"
void CompressorETC1 : : compressBlock ( Vector4 colors [ 16 ] , float weights [ 16 ] , const CompressionOptions : : Private & compressionOptions , void * output )
{
compress_etc1 ( colors , weights , compressionOptions . colorWeight . xyz ( ) , output ) ;
}
void CompressorETC2_R : : compressBlock ( Vector4 colors [ 16 ] , float weights [ 16 ] , const CompressionOptions : : Private & compressionOptions , void * output )
{
// @@ Change radius based on quality.
compress_eac ( colors , weights , /*input_channel=*/ 1 , /*search_radius=*/ 1 , /*use_11bit_mode=*/ true , output ) ;
}
void CompressorETC2_RG : : compressBlock ( Vector4 colors [ 16 ] , float weights [ 16 ] , const CompressionOptions : : Private & compressionOptions , void * output )
{
//compress_eac_rg(colors, weights, 1, 2, output);
}
void CompressorETC2_RGB : : compressBlock ( Vector4 colors [ 16 ] , float weights [ 16 ] , const CompressionOptions : : Private & compressionOptions , void * output )
{
// @@ Tweak quality options.
compress_etc2 ( colors , weights , compressionOptions . colorWeight . xyz ( ) , output ) ;
}
void CompressorETC2_RGBA : : compressBlock ( Vector4 colors [ 16 ] , float weights [ 16 ] , const CompressionOptions : : Private & compressionOptions , void * output )
{
// @@ Tweak quality options.
// @@ Change radius based on quality.
compress_etc2_eac ( colors , weights , compressionOptions . colorWeight . xyz ( ) , output ) ;
}
/*void CompressorETC2_RG::compressBlock(Vector4 colors[16], float weights[16], const CompressionOptions::Private & compressionOptions, void * output)
{
// @@ Change radius based on quality.
compress_eac_rg ( colors , weights , compressionOptions . colorWeight . xyz ( ) , output ) ;
} */
void CompressorETC2_RGBM : : compressBlock ( Vector4 colors [ 16 ] , float weights [ 16 ] , const CompressionOptions : : Private & compressionOptions , void * output )
{
compress_etc2_rgbm ( colors , weights , compressionOptions . rgbmThreshold , output ) ;
}
// External compressors.
# if defined(HAVE_ATITC)
typedef int BOOL ;
typedef _W64 unsigned long ULONG_PTR ;
typedef ULONG_PTR DWORD_PTR ;
# include "atitc/ATI_Compress.h"
void AtiCompressorDXT1 : : compress ( InputFormat inputFormat , AlphaMode alphaMode , uint w , uint h , uint d , void * data , const CompressionOptions : : Private & compressionOptions , const OutputOptions : : Private & outputOptions )
{
nvDebugCheck ( d = = 1 ) ;
// Init source texture
ATI_TC_Texture srcTexture ;
srcTexture . dwSize = sizeof ( srcTexture ) ;
srcTexture . dwWidth = w ;
srcTexture . dwHeight = h ;
if ( inputFormat = = InputFormat_BGRA_8UB )
{
srcTexture . dwPitch = w * 4 ;
srcTexture . format = ATI_TC_FORMAT_ARGB_8888 ;
}
else
{
// @@ Floating point input is not swizzled.
srcTexture . dwPitch = w * 16 ;
srcTexture . format = ATI_TC_FORMAT_ARGB_32F ;
}
srcTexture . dwDataSize = ATI_TC_CalculateBufferSize ( & srcTexture ) ;
srcTexture . pData = ( ATI_TC_BYTE * ) data ;
// Init dest texture
ATI_TC_Texture destTexture ;
destTexture . dwSize = sizeof ( destTexture ) ;
destTexture . dwWidth = w ;
destTexture . dwHeight = h ;
destTexture . dwPitch = 0 ;
destTexture . format = ATI_TC_FORMAT_DXT1 ;
destTexture . dwDataSize = ATI_TC_CalculateBufferSize ( & destTexture ) ;
destTexture . pData = ( ATI_TC_BYTE * ) mem : : malloc ( destTexture . dwDataSize ) ;
ATI_TC_CompressOptions options ;
options . dwSize = sizeof ( options ) ;
options . bUseChannelWeighting = false ;
options . bUseAdaptiveWeighting = false ;
options . bDXT1UseAlpha = false ;
options . nCompressionSpeed = ATI_TC_Speed_Normal ;
options . bDisableMultiThreading = false ;
//options.bDisableMultiThreading = true;
// Compress
ATI_TC_ConvertTexture ( & srcTexture , & destTexture , & options , NULL , NULL , NULL ) ;
if ( outputOptions . outputHandler ! = NULL ) {
outputOptions . outputHandler - > writeData ( destTexture . pData , destTexture . dwDataSize ) ;
}
mem : : free ( destTexture . pData ) ;
}
void AtiCompressorDXT5 : : compress ( InputFormat inputFormat , AlphaMode alphaMode , uint w , uint h , uint d , void * data , const CompressionOptions : : Private & compressionOptions , const OutputOptions : : Private & outputOptions )
{
nvDebugCheck ( d = = 1 ) ;
// Init source texture
ATI_TC_Texture srcTexture ;
srcTexture . dwSize = sizeof ( srcTexture ) ;
srcTexture . dwWidth = w ;
srcTexture . dwHeight = h ;
if ( inputFormat = = InputFormat_BGRA_8UB )
{
srcTexture . dwPitch = w * 4 ;
srcTexture . format = ATI_TC_FORMAT_ARGB_8888 ;
}
else
{
srcTexture . dwPitch = w * 16 ;
srcTexture . format = ATI_TC_FORMAT_ARGB_32F ;
}
srcTexture . dwDataSize = ATI_TC_CalculateBufferSize ( & srcTexture ) ;
srcTexture . pData = ( ATI_TC_BYTE * ) data ;
// Init dest texture
ATI_TC_Texture destTexture ;
destTexture . dwSize = sizeof ( destTexture ) ;
destTexture . dwWidth = w ;
destTexture . dwHeight = h ;
destTexture . dwPitch = 0 ;
destTexture . format = ATI_TC_FORMAT_DXT5 ;
destTexture . dwDataSize = ATI_TC_CalculateBufferSize ( & destTexture ) ;
destTexture . pData = ( ATI_TC_BYTE * ) mem : : malloc ( destTexture . dwDataSize ) ;
// Compress
ATI_TC_ConvertTexture ( & srcTexture , & destTexture , NULL , NULL , NULL , NULL ) ;
if ( outputOptions . outputHandler ! = NULL ) {
outputOptions . outputHandler - > writeData ( destTexture . pData , destTexture . dwDataSize ) ;
}
mem : : free ( destTexture . pData ) ;
}
# endif // defined(HAVE_ATITC)
# if defined(HAVE_SQUISH)
//#include "squish/squish.h"
# include "squish-1.10/squish.h"
void SquishCompressorDXT1 : : compress ( InputFormat inputFormat , AlphaMode alphaMode , uint w , uint h , uint d , void * data , const CompressionOptions : : Private & compressionOptions , const OutputOptions : : Private & outputOptions )
{
nvDebugCheck ( d = = 1 ) ;
nvDebugCheck ( false ) ;
# pragma message(NV_FILE_LINE "TODO: Convert input to fixed point ABGR format instead of ARGB")
/*
Image img ( * image ) ;
int count = img . width ( ) * img . height ( ) ;
for ( int i = 0 ; i < count ; i + + )
{
Color32 c = img . pixel ( i ) ;
img . pixel ( i ) = Color32 ( c . b , c . g , c . r , c . a ) ;
}
int size = squish : : GetStorageRequirements ( img . width ( ) , img . height ( ) , squish : : kDxt1 ) ;
void * blocks = mem : : malloc ( size ) ;
squish : : CompressImage ( ( const squish : : u8 * ) img . pixels ( ) , img . width ( ) , img . height ( ) , blocks , squish : : kDxt1 | squish : : kColourClusterFit ) ;
if ( outputOptions . outputHandler ! = NULL ) {
outputOptions . outputHandler - > writeData ( blocks , size ) ;
}
mem : : free ( blocks ) ;
*/
}
# endif // defined(HAVE_SQUISH)
# if defined(HAVE_D3DX)
void D3DXCompressorDXT1 : : compress ( InputFormat inputFormat , AlphaMode alphaMode , uint w , uint h , uint d , void * data , const CompressionOptions : : Private & compressionOptions , const OutputOptions : : Private & outputOptions )
{
nvDebugCheck ( d = = 1 ) ;
IDirect3D9 * d3d = Direct3DCreate9 ( D3D_SDK_VERSION ) ;
D3DPRESENT_PARAMETERS presentParams ;
ZeroMemory ( & presentParams , sizeof ( presentParams ) ) ;
presentParams . Windowed = TRUE ;
presentParams . SwapEffect = D3DSWAPEFFECT_COPY ;
presentParams . BackBufferWidth = 8 ;
presentParams . BackBufferHeight = 8 ;
presentParams . BackBufferFormat = D3DFMT_UNKNOWN ;
HRESULT err ;
IDirect3DDevice9 * device = NULL ;
err = d3d - > CreateDevice ( D3DADAPTER_DEFAULT , D3DDEVTYPE_REF , GetDesktopWindow ( ) , D3DCREATE_SOFTWARE_VERTEXPROCESSING , & presentParams , & device ) ;
IDirect3DTexture9 * texture = NULL ;
err = D3DXCreateTexture ( device , w , h , 1 , 0 , D3DFMT_DXT1 , D3DPOOL_SYSTEMMEM , & texture ) ;
IDirect3DSurface9 * surface = NULL ;
err = texture - > GetSurfaceLevel ( 0 , & surface ) ;
RECT rect ;
rect . left = 0 ;
rect . top = 0 ;
rect . bottom = h ;
rect . right = w ;
if ( inputFormat = = InputFormat_BGRA_8UB )
{
err = D3DXLoadSurfaceFromMemory ( surface , NULL , NULL , data , D3DFMT_A8R8G8B8 , w * 4 , NULL , & rect , D3DX_DEFAULT , 0 ) ;
}
else
{
err = D3DXLoadSurfaceFromMemory ( surface , NULL , NULL , data , D3DFMT_A32B32G32R32F , w * 16 , NULL , & rect , D3DX_DEFAULT , 0 ) ;
}
if ( err ! = D3DERR_INVALIDCALL & & err ! = D3DXERR_INVALIDDATA )
{
D3DLOCKED_RECT rect ;
ZeroMemory ( & rect , sizeof ( rect ) ) ;
err = surface - > LockRect ( & rect , NULL , D3DLOCK_READONLY ) ;
if ( outputOptions . outputHandler ! = NULL ) {
int size = rect . Pitch * ( ( h + 3 ) / 4 ) ;
outputOptions . outputHandler - > writeData ( rect . pBits , size ) ;
}
err = surface - > UnlockRect ( ) ;
}
surface - > Release ( ) ;
device - > Release ( ) ;
d3d - > Release ( ) ;
}
# endif // defined(HAVE_D3DX)
# if defined(HAVE_STB)
# define STB_DEFINE
# include "stb/stb_dxt.h"
void StbCompressorDXT1 : : compressBlock ( ColorBlock & rgba , AlphaMode alphaMode , const CompressionOptions : : Private & compressionOptions , void * output )
{
rgba . swizzle ( 2 , 1 , 0 , 3 ) ; // Swap R and B
stb_compress_dxt_block ( ( unsigned char * ) output , ( unsigned char * ) rgba . colors ( ) , 0 , 0 ) ;
}
# endif // defined(HAVE_STB)
# if defined(HAVE_ETCLIB)
# include "Etc.h"
void EtcLibCompressor : : compress ( AlphaMode alphaMode , uint w , uint h , uint d , const float * data , TaskDispatcher * dispatcher , const CompressionOptions : : Private & compressionOptions , const OutputOptions : : Private & outputOptions )
{
//nvCheck(d == 1); // Encode one layer at a time?
Etc : : Image : : Format format ;
if ( compressionOptions . format = = Format_ETC1 ) {
format = Etc : : Image : : Format : : ETC1 ;
}
else if ( compressionOptions . format = = Format_ETC2_R ) {
format = Etc : : Image : : Format : : R11 ;
}
else if ( compressionOptions . format = = Format_ETC2_RG ) {
format = Etc : : Image : : Format : : RG11 ;
}
else if ( compressionOptions . format = = Format_ETC2_RGB ) {
format = Etc : : Image : : Format : : RGB8 ;
//format = Etc::Image::Format::SRGB8;
}
else if ( compressionOptions . format = = Format_ETC2_RGBA ) {
format = Etc : : Image : : Format : : RGBA8 ;
//format = Etc::Image::Format::SRGBA8;
}
else if ( compressionOptions . format = = Format_ETC2_RGB_A1 ) {
format = Etc : : Image : : Format : : RGB8A1 ;
//format = Etc::Image::Format::SRGB8A1;
}
else {
nvCheck ( false ) ;
return ;
}
Etc : : ErrorMetric error_metric = Etc : : ErrorMetric : : RGBA ;
// @@ Use normal compression metric for normals?
//if (compressionOptions.)
// @@ Adjust based on quality.
int effort = ETCCOMP_DEFAULT_EFFORT_LEVEL ;
// @@ What are the defaults?
uint jobs = 4 ;
uint max_jobs = 4 ;
uint8 * out_data = NULL ;
uint out_size = 0 ;
uint out_width = 0 ;
uint out_height = 0 ;
int out_time = 0 ;
// Swizzle color data.
nv : : Array < float > tmp ;
uint count = w * h ;
tmp . resize ( 4 * count ) ;
for ( uint i = 0 ; i < count ; i + + ) {
tmp [ 4 * i + 0 ] = data [ count * 0 + i ] ;
tmp [ 4 * i + 1 ] = data [ count * 1 + i ] ;
tmp [ 4 * i + 2 ] = data [ count * 2 + i ] ;
tmp [ 4 * i + 3 ] = data [ count * 3 + i ] ;
}
Etc : : Encode ( tmp . buffer ( ) , w , h , format , error_metric , effort , jobs , max_jobs , & out_data , & out_size , & out_width , & out_height , & out_time ) ;
if ( outputOptions . outputHandler ! = NULL ) {
outputOptions . outputHandler - > writeData ( out_data , I32 ( out_size ) ) ;
}
}
# endif
# if defined(HAVE_RGETC)
# include "rg_etc1.h"
NV_AT_STARTUP ( rg_etc1 : : pack_etc1_block_init ( ) ) ;
void RgEtcCompressor : : compressBlock ( ColorBlock & rgba , AlphaMode alphaMode , const CompressionOptions : : Private & compressionOptions , void * output )
{
rg_etc1 : : etc1_pack_params pack_params ;
pack_params . m_quality = rg_etc1 : : cMediumQuality ;
if ( compressionOptions . quality = = Quality_Fastest ) pack_params . m_quality = rg_etc1 : : cLowQuality ;
else if ( compressionOptions . quality = = Quality_Production ) pack_params . m_quality = rg_etc1 : : cHighQuality ;
else if ( compressionOptions . quality = = Quality_Highest ) pack_params . m_quality = rg_etc1 : : cHighQuality ;
else if ( compressionOptions . quality = = Quality_Normal ) pack_params . m_quality = rg_etc1 : : cMediumQuality ;
rgba . swizzle ( 2 , 1 , 0 , 3 ) ;
rg_etc1 : : pack_etc1_block ( output , ( uint * ) rgba . colors ( ) , pack_params ) ;
//Vector4 result[16];
//nv::decompress_etc(output, result);
}
# endif
# if defined(HAVE_PVRTEXTOOL)
# include <PVRTextureUtilities.h> // for CPVRTexture, CPVRTextureHeader, PixelType, Transcode
# include "nvmath/Color.inl"
void CompressorPVR : : compress ( AlphaMode alphaMode , uint w , uint h , uint d , const float * data , TaskDispatcher * dispatcher , const CompressionOptions : : Private & compressionOptions , const OutputOptions : : Private & outputOptions )
{
EPVRTColourSpace color_space = ePVRTCSpacelRGB ;
//pvrtexture::PixelType src_pixel_type = pvrtexture::PixelType('b','g','r','a',8,8,8,8);
pvrtexture : : PixelType src_pixel_type = pvrtexture : : PixelType ( ' r ' , ' g ' , ' b ' , 0 , 8 , 8 , 8 , 0 ) ;
pvrtexture : : CPVRTextureHeader header ( src_pixel_type . PixelTypeID , w , h , d , 1 /*num mips*/ , 1 /*num array*/ , 1 /*num faces*/ , color_space , ePVRTVarTypeUnsignedByteNorm ) ;
/*
uint count = w * h * d ;
Array < Color32 > tmp ;
tmp . resize ( count ) ;
for ( uint i = 0 ; i < count ; i + + ) {
tmp [ i ] = toColor32 ( Vector4 ( data [ 0 * count + i ] , data [ 1 * count + i ] , data [ 2 * count + i ] , data [ 3 * count + i ] ) ) ;
}
*/
uint count = w * h * d ;
Array < uint8 > tmp ;
tmp . resize ( 3 * count ) ;
for ( uint i = 0 ; i < count ; i + + ) {
tmp [ 3 * i + 0 ] = data [ 0 * count + i ] * 255.0f ;
tmp [ 3 * i + 1 ] = data [ 1 * count + i ] * 255.0f ;
tmp [ 3 * i + 2 ] = data [ 2 * count + i ] * 255.0f ;
}
pvrtexture : : CPVRTexture texture ( header , tmp . buffer ( ) ) ;
pvrtexture : : PixelType dst_pixel_type = pvrtexture : : PixelType ( ePVRTPF_PVRTCI_2bpp_RGB ) ;
if ( compressionOptions . format = = Format_PVR_2BPP_RGB ) dst_pixel_type = pvrtexture : : PixelType ( ePVRTPF_PVRTCI_2bpp_RGB ) ;
else if ( compressionOptions . format = = Format_PVR_4BPP_RGB ) dst_pixel_type = pvrtexture : : PixelType ( ePVRTPF_PVRTCI_4bpp_RGB ) ;
else if ( compressionOptions . format = = Format_PVR_2BPP_RGBA ) dst_pixel_type = pvrtexture : : PixelType ( ePVRTPF_PVRTCI_2bpp_RGBA ) ;
else if ( compressionOptions . format = = Format_PVR_4BPP_RGBA ) dst_pixel_type = pvrtexture : : PixelType ( ePVRTPF_PVRTCI_4bpp_RGBA ) ;
bool success = pvrtexture : : Transcode ( texture , dst_pixel_type , ePVRTVarTypeUnsignedByteNorm , color_space , pvrtexture : : ePVRTCNormal , false ) ;
if ( success ) {
uint size = 0 ;
if ( compressionOptions . format = = Format_PVR_2BPP_RGB | | compressionOptions . format = = Format_PVR_2BPP_RGBA ) {
// 2 bpp
const uint bpp = 2u ;
const uint block_size = 8u * 4u ;
const uint size_factor = ( block_size * bpp ) > > 3u ;
const uint block_width = nv : : max ( ( w > > 3u ) , 2u ) ;
const uint block_height = nv : : max ( ( h > > 2u ) , 2u ) ;
size = d * block_width * block_height * size_factor ;
}
else {
// 4 bpp
const uint bpp = 4u ;
const uint block_size = 4u * 4u ;
const uint size_factor = ( block_size * bpp ) > > 3u ;
const uint block_width = max ( ( w > > 2u ) , 2u ) ;
const uint block_height = max ( ( h > > 2u ) , 2u ) ;
size = d * block_width * block_height * size_factor ;
}
if ( outputOptions . outputHandler ! = NULL ) {
outputOptions . outputHandler - > writeData ( texture . getDataPtr ( ) , I32 ( size ) ) ;
}
}
}
# endif