Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- static tracy_force_inline uint64_t ProcessRGB( const uint8_t* src )
- {
- #ifdef __SSE4_1__
- __m128i px0 = _mm_loadu_si128(((__m128i*)src) + 0);
- __m128i px1 = _mm_loadu_si128(((__m128i*)src) + 1);
- __m128i px2 = _mm_loadu_si128(((__m128i*)src) + 2);
- __m128i px3 = _mm_loadu_si128(((__m128i*)src) + 3);
- __m128i smask = _mm_set1_epi32( 0xF8FCF8 );
- __m128i sd0 = _mm_and_si128( px0, smask );
- __m128i sd1 = _mm_and_si128( px1, smask );
- __m128i sd2 = _mm_and_si128( px2, smask );
- __m128i sd3 = _mm_and_si128( px3, smask );
- __m128i sc = _mm_shuffle_epi32(sd0, _MM_SHUFFLE(0, 0, 0, 0));
- __m128i sc0 = _mm_cmpeq_epi8(sd0, sc);
- __m128i sc1 = _mm_cmpeq_epi8(sd1, sc);
- __m128i sc2 = _mm_cmpeq_epi8(sd2, sc);
- __m128i sc3 = _mm_cmpeq_epi8(sd3, sc);
- __m128i sm0 = _mm_and_si128(sc0, sc1);
- __m128i sm1 = _mm_and_si128(sc2, sc3);
- __m128i sm = _mm_and_si128(sm0, sm1);
- if( _mm_testc_si128(sm, _mm_set1_epi32(-1)) )
- {
- return uint64_t( to565( src[0], src[1], src[2] ) ) << 16;
- }
- __m128i min0 = _mm_min_epu8( px0, px1 );
- __m128i min1 = _mm_min_epu8( px2, px3 );
- __m128i min2 = _mm_min_epu8( min0, min1 );
- __m128i max0 = _mm_max_epu8( px0, px1 );
- __m128i max1 = _mm_max_epu8( px2, px3 );
- __m128i max2 = _mm_max_epu8( max0, max1 );
- __m128i min3 = _mm_shuffle_epi32( min2, _MM_SHUFFLE( 2, 3, 0, 1 ) );
- __m128i max3 = _mm_shuffle_epi32( max2, _MM_SHUFFLE( 2, 3, 0, 1 ) );
- __m128i min4 = _mm_min_epu8( min2, min3 );
- __m128i max4 = _mm_max_epu8( max2, max3 );
- __m128i min5 = _mm_shuffle_epi32( min4, _MM_SHUFFLE( 0, 0, 2, 2 ) );
- __m128i max5 = _mm_shuffle_epi32( max4, _MM_SHUFFLE( 0, 0, 2, 2 ) );
- __m128i rmin = _mm_min_epu8( min4, min5 );
- __m128i rmax = _mm_max_epu8( max4, max5 );
- __m128i range1 = _mm_subs_epu8( rmax, rmin );
- __m128i range2 = _mm_sad_epu8( rmax, rmin );
- uint32_t vrange = _mm_cvtsi128_si32( range2 ) >> 1;
- __m128i range = _mm_set1_epi16( DivTable[vrange] );
- __m128i inset1 = _mm_srli_epi16( range1, 4 );
- __m128i inset = _mm_and_si128( inset1, _mm_set1_epi8( 0xF ) );
- __m128i min = _mm_adds_epu8( rmin, inset );
- __m128i max = _mm_subs_epu8( rmax, inset );
- __m128i c0 = _mm_subs_epu8( px0, rmin );
- __m128i c1 = _mm_subs_epu8( px1, rmin );
- __m128i c2 = _mm_subs_epu8( px2, rmin );
- __m128i c3 = _mm_subs_epu8( px3, rmin );
- __m128i is0 = _mm_maddubs_epi16( c0, _mm_set1_epi8( 1 ) );
- __m128i is1 = _mm_maddubs_epi16( c1, _mm_set1_epi8( 1 ) );
- __m128i is2 = _mm_maddubs_epi16( c2, _mm_set1_epi8( 1 ) );
- __m128i is3 = _mm_maddubs_epi16( c3, _mm_set1_epi8( 1 ) );
- __m128i s0 = _mm_hadd_epi16( is0, is1 );
- __m128i s1 = _mm_hadd_epi16( is2, is3 );
- __m128i m0 = _mm_mulhi_epu16( s0, range );
- __m128i m1 = _mm_mulhi_epu16( s1, range );
- __m128i p0 = _mm_packus_epi16( m0, m1 );
- __m128i p1 = _mm_or_si128( _mm_srai_epi32( p0, 6 ), _mm_srai_epi32( p0, 12 ) );
- __m128i p2 = _mm_or_si128( _mm_srai_epi32( p0, 18 ), p0 );
- __m128i p3 = _mm_or_si128( p1, p2 );
- __m128i p =_mm_shuffle_epi8( p3, _mm_set1_epi32( 0x0C080400 ) );
- uint32_t vmin = _mm_cvtsi128_si32( min );
- uint32_t vmax = _mm_cvtsi128_si32( max );
- uint32_t vp = _mm_cvtsi128_si32( p );
- return uint64_t( ( uint64_t( to565( vmin ) ) << 16 ) | to565( vmax ) | ( uint64_t( vp ) << 32 ) );
- #else
- const auto ref = to565( src[0], src[1], src[2] );
- auto stmp = src + 4;
- for( int i=1; i<16; i++ )
- {
- if( to565( stmp[0], stmp[1], stmp[2] ) != ref )
- {
- break;
- }
- stmp += 4;
- }
- if( stmp == src + 64 )
- {
- return uint64_t( ref ) << 16;
- }
- uint8_t min[3] = { src[0], src[1], src[2] };
- uint8_t max[3] = { src[0], src[1], src[2] };
- auto tmp = src + 4;
- for( int i=1; i<16; i++ )
- {
- for( int j=0; j<3; j++ )
- {
- if( tmp[j] < min[j] ) min[j] = tmp[j];
- else if( tmp[j] > max[j] ) max[j] = tmp[j];
- }
- tmp += 4;
- }
- const uint32_t range = DivTable[max[0] - min[0] + max[1] - min[1] + max[2] - min[2]];
- const uint32_t rmin = min[0] + min[1] + min[2];
- for( int i=0; i<3; i++ )
- {
- const uint8_t inset = ( max[i] - min[i] ) >> 4;
- min[i] += inset;
- max[i] -= inset;
- }
- uint32_t data = 0;
- for( int i=0; i<16; i++ )
- {
- const uint32_t c = src[0] + src[1] + src[2] - rmin;
- const uint8_t idx = ( c * range ) >> 16;
- data |= idx << (i*2);
- src += 4;
- }
- return uint64_t( ( uint64_t( to565( min[0], min[1], min[2] ) ) << 16 ) | to565( max[0], max[1], max[2] ) | ( uint64_t( data ) << 32 ) );
- #endif
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement