// Copyright 2014 Google Inc. All Rights Reserved. // // Use of this source code is governed by a BSD-style license // that can be found in the COPYING file in the root of the source // tree. An additional intellectual property rights grant can be found // in the file PATENTS. All contributing project authors may // be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Utilities for processing transparent channel. // // Author: Skal (pascal.massimino@gmail.com)
staticint DispatchAlpha_SSE2(const uint8_t* WEBP_RESTRICT alpha, int alpha_stride, int width, int height,
uint8_t* WEBP_RESTRICT dst, int dst_stride) { // alpha_and stores an 'and' operation of all the alpha[] values. The final // value is not 0xff if any of the alpha[] is not equal to 0xff.
uint32_t alpha_and = 0xff; int i, j; const __m128i zero = _mm_setzero_si128(); const __m128i alpha_mask = _mm_set1_epi32((int)0xff); // to preserve A const __m128i all_0xff = _mm_set1_epi8((char)0xff);
__m128i all_alphas16 = all_0xff;
__m128i all_alphas8 = all_0xff;
// We must be able to access 3 extra bytes after the last written byte // 'dst[4 * width - 4]', because we don't know if alpha is the first or the // last byte of the quadruplet. for (j = 0; j < height; ++j) { char* ptr = (char*)dst; for (i = 0; i + 16 <= width - 1; i += 16) { // load 16 alpha bytes const __m128i a0 = _mm_loadu_si128((const __m128i*)&alpha[i]); const __m128i a1_lo = _mm_unpacklo_epi8(a0, zero); const __m128i a1_hi = _mm_unpackhi_epi8(a0, zero); const __m128i a2_lo_lo = _mm_unpacklo_epi16(a1_lo, zero); const __m128i a2_lo_hi = _mm_unpackhi_epi16(a1_lo, zero); const __m128i a2_hi_lo = _mm_unpacklo_epi16(a1_hi, zero); const __m128i a2_hi_hi = _mm_unpackhi_epi16(a1_hi, zero);
_mm_maskmoveu_si128(a2_lo_lo, alpha_mask, ptr + 0);
_mm_maskmoveu_si128(a2_lo_hi, alpha_mask, ptr + 16);
_mm_maskmoveu_si128(a2_hi_lo, alpha_mask, ptr + 32);
_mm_maskmoveu_si128(a2_hi_hi, alpha_mask, ptr + 48); // accumulate 16 alpha 'and' in parallel
all_alphas16 = _mm_and_si128(all_alphas16, a0);
ptr += 64;
} if (i + 8 <= width - 1) { // load 8 alpha bytes const __m128i a0 = _mm_loadl_epi64((const __m128i*)&alpha[i]); const __m128i a1 = _mm_unpacklo_epi8(a0, zero); const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero); const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero);
_mm_maskmoveu_si128(a2_lo, alpha_mask, ptr);
_mm_maskmoveu_si128(a2_hi, alpha_mask, ptr + 16); // accumulate 8 alpha 'and' in parallel
all_alphas8 = _mm_and_si128(all_alphas8, a0);
i += 8;
} for (; i < width; ++i) { const uint32_t alpha_value = alpha[i];
dst[4 * i] = alpha_value;
alpha_and &= alpha_value;
}
alpha += alpha_stride;
dst += dst_stride;
} // Combine the eight alpha 'and' into a 8-bit mask.
alpha_and &= _mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas8, all_0xff)) & 0xff; return (alpha_and != 0xff ||
_mm_movemask_epi8(_mm_cmpeq_epi8(all_alphas16, all_0xff)) != 0xffff);
}
staticvoid DispatchAlphaToGreen_SSE2(const uint8_t* WEBP_RESTRICT alpha, int alpha_stride, int width, int height,
uint32_t* WEBP_RESTRICT dst, int dst_stride) { int i, j; const __m128i zero = _mm_setzero_si128(); constint limit = width & ~15; for (j = 0; j < height; ++j) { for (i = 0; i < limit; i += 16) { // process 16 alpha bytes const __m128i a0 = _mm_loadu_si128((const __m128i*)&alpha[i]); const __m128i a1 = _mm_unpacklo_epi8(zero, a0); // note the 'zero' first! const __m128i b1 = _mm_unpackhi_epi8(zero, a0); const __m128i a2_lo = _mm_unpacklo_epi16(a1, zero); const __m128i b2_lo = _mm_unpacklo_epi16(b1, zero); const __m128i a2_hi = _mm_unpackhi_epi16(a1, zero); const __m128i b2_hi = _mm_unpackhi_epi16(b1, zero);
_mm_storeu_si128((__m128i*)&dst[i + 0], a2_lo);
_mm_storeu_si128((__m128i*)&dst[i + 4], a2_hi);
_mm_storeu_si128((__m128i*)&dst[i + 8], b2_lo);
_mm_storeu_si128((__m128i*)&dst[i + 12], b2_hi);
} for (; i < width; ++i) dst[i] = alpha[i] << 8;
alpha += alpha_stride;
dst += dst_stride;
}
}
staticint ExtractAlpha_SSE2(const uint8_t* WEBP_RESTRICT argb, int argb_stride, int width, int height,
uint8_t* WEBP_RESTRICT alpha, int alpha_stride) { // alpha_and stores an 'and' operation of all the alpha[] values. The final // value is not 0xff if any of the alpha[] is not equal to 0xff.
uint32_t alpha_and = 0xff; int i, j; const __m128i a_mask = _mm_set1_epi32(0xff); // to preserve alpha const __m128i all_0xff = _mm_set_epi32(0, 0, ~0, ~0);
__m128i all_alphas = all_0xff;
// We must be able to access 3 extra bytes after the last written byte // 'src[4 * width - 4]', because we don't know if alpha is the first or the // last byte of the quadruplet. constint limit = (width - 1) & ~7;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.