medfall

A super great game engine
Log | Files | Refs

decompress_bc.cc (1915B)


      1 #include "intrinsics.h"
      2 #include "linear_algebra.h"
      3 #include "array.h"
      4 
      5 struct AlphaBlock {
      6 	union {
      7 		u64 block;
      8 		struct {
      9 			u8 endpoints[ 2 ];
     10 			u8 selectors[ 6 ];
     11 		};
     12 	};
     13 };
     14 
     15 static void get_values( float ( &values )[ 8 ], u8 e0, u8 e1 ) {
     16 	values[ 0 ] = e0 / 255.0f;
     17 	values[ 1 ] = e1 / 255.0f;
     18 
     19 	if( e0 > e1 ) {
     20 		values[ 2 ] = ( values[ 0 ] * 6 + values[ 1 ] * 1 ) / 7;
     21 		values[ 3 ] = ( values[ 0 ] * 5 + values[ 1 ] * 2 ) / 7;
     22 		values[ 4 ] = ( values[ 0 ] * 4 + values[ 1 ] * 3 ) / 7;
     23 		values[ 5 ] = ( values[ 0 ] * 3 + values[ 1 ] * 4 ) / 7;
     24 		values[ 6 ] = ( values[ 0 ] * 2 + values[ 1 ] * 5 ) / 7;
     25 		values[ 7 ] = ( values[ 0 ] * 1 + values[ 1 ] * 6 ) / 7;
     26 	}
     27 	else {
     28 		values[ 2 ] = ( values[ 0 ] * 4 + values[ 1 ] * 1 ) / 5;
     29 		values[ 3 ] = ( values[ 0 ] * 3 + values[ 1 ] * 2 ) / 5;
     30 		values[ 4 ] = ( values[ 0 ] * 2 + values[ 1 ] * 3 ) / 5;
     31 		values[ 5 ] = ( values[ 0 ] * 1 + values[ 1 ] * 4 ) / 5;
     32 		values[ 6 ] = 0.0f;
     33 		values[ 7 ] = 1.0f;
     34 	}
     35 }
     36 
     37 template< typename T, typename Comp >
     38 static void decompress_alpha_block( array2d< T > img, Comp comp, size_t img_x, size_t img_y, const AlphaBlock * block ) {
     39 	float values[ 8 ];
     40 	get_values( values, block->endpoints[ 0 ], block->endpoints[ 1 ] );
     41 
     42 	for( u32 y = 0; y < 4; y++ ) {
     43 		for( u32 x = 0; x < 4; x++ ) {
     44 			u32 selector_bit = 3 * ( y * 4 + x );
     45 			u64 selector = ( block->block >> ( 16 + selector_bit ) ) & 7;
     46 
     47 			comp( img( img_x + x, img_y + y ) ) = values[ selector ];
     48 		}
     49 	}
     50 }
     51 
     52 static float & R( v2 & rg ) {
     53 	return rg.x;
     54 }
     55 
     56 static float & G( v2 & rg ) {
     57 	return rg.y;
     58 }
     59 
     60 void decompress_bc5( array2d< v2 > img, const u8 * bc5 ) {
     61 	const AlphaBlock * blocks = ( const AlphaBlock * ) bc5;
     62 
     63 	size_t i = 0;
     64 	for( size_t y = 0; y < img.h; y += 4 ) {
     65 		for( size_t x = 0; x < img.w; x += 4 ) {
     66 			decompress_alpha_block( img, R, x, y, &blocks[ i ] );
     67 			i++;
     68 			decompress_alpha_block( img, G, x, y, &blocks[ i ] );
     69 			i++;
     70 		}
     71 	}
     72 }