libwebp: Sync with upstream 1.3.0

This commit is contained in:
DeeJayLSP 2023-01-25 10:24:01 -03:00
parent 6369196b96
commit d8e8517d11
47 changed files with 377 additions and 268 deletions

View file

@ -13,6 +13,7 @@ if env["builtin_libwebp"]:
thirdparty_dir = "#thirdparty/libwebp/" thirdparty_dir = "#thirdparty/libwebp/"
thirdparty_sources = [ thirdparty_sources = [
"sharpyuv/sharpyuv.c", "sharpyuv/sharpyuv.c",
"sharpyuv/sharpyuv_cpu.c",
"sharpyuv/sharpyuv_csp.c", "sharpyuv/sharpyuv_csp.c",
"sharpyuv/sharpyuv_dsp.c", "sharpyuv/sharpyuv_dsp.c",
"sharpyuv/sharpyuv_gamma.c", "sharpyuv/sharpyuv_gamma.c",

View file

@ -346,7 +346,7 @@ Files extracted from upstream source:
## libwebp ## libwebp
- Upstream: https://chromium.googlesource.com/webm/libwebp/ - Upstream: https://chromium.googlesource.com/webm/libwebp/
- Version: 1.2.4 (0d1f12546bd803099a60c070517a552483f3790e, 2022) - Version: 1.3.0 (b557776962a3dcc985d83bd4ed94e1e2e50d0fa2, 2022)
- License: BSD-3-Clause - License: BSD-3-Clause
Files extracted from upstream source: Files extracted from upstream source:

View file

@ -11,11 +11,13 @@ Contributors:
- Djordje Pesut (djordje dot pesut at imgtec dot com) - Djordje Pesut (djordje dot pesut at imgtec dot com)
- Frank Barchard (fbarchard at google dot com) - Frank Barchard (fbarchard at google dot com)
- Hui Su (huisu at google dot com) - Hui Su (huisu at google dot com)
- H. Vetinari (h dot vetinari at gmx dot com)
- Ilya Kurdyukov (jpegqs at gmail dot com) - Ilya Kurdyukov (jpegqs at gmail dot com)
- Ingvar Stepanyan (rreverser at google dot com) - Ingvar Stepanyan (rreverser at google dot com)
- James Zern (jzern at google dot com) - James Zern (jzern at google dot com)
- Jan Engelhardt (jengelh at medozas dot de) - Jan Engelhardt (jengelh at medozas dot de)
- Jehan (jehan at girinstud dot io) - Jehan (jehan at girinstud dot io)
- Jeremy Maitin-Shepard (jbms at google dot com)
- Johann Koenig (johann dot koenig at duck dot com) - Johann Koenig (johann dot koenig at duck dot com)
- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com) - Jovan Zelincevic (jovan dot zelincevic at imgtec dot com)
- Jyrki Alakuijala (jyrki at google dot com) - Jyrki Alakuijala (jyrki at google dot com)

View file

@ -15,15 +15,21 @@
#include <assert.h> #include <assert.h>
#include <limits.h> #include <limits.h>
#include <math.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "src/webp/types.h" #include "src/webp/types.h"
#include "src/dsp/cpu.h" #include "sharpyuv/sharpyuv_cpu.h"
#include "sharpyuv/sharpyuv_dsp.h" #include "sharpyuv/sharpyuv_dsp.h"
#include "sharpyuv/sharpyuv_gamma.h" #include "sharpyuv/sharpyuv_gamma.h"
//------------------------------------------------------------------------------
int SharpYuvGetVersion(void) {
return SHARPYUV_VERSION;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Sharp RGB->YUV conversion // Sharp RGB->YUV conversion
@ -414,24 +420,45 @@ static int DoSharpArgbToYuv(const uint8_t* r_ptr, const uint8_t* g_ptr,
} }
#undef SAFE_ALLOC #undef SAFE_ALLOC
#if defined(WEBP_USE_THREAD) && !defined(_WIN32)
#include <pthread.h> // NOLINT
#define LOCK_ACCESS \
static pthread_mutex_t sharpyuv_lock = PTHREAD_MUTEX_INITIALIZER; \
if (pthread_mutex_lock(&sharpyuv_lock)) return
#define UNLOCK_ACCESS_AND_RETURN \
do { \
(void)pthread_mutex_unlock(&sharpyuv_lock); \
return; \
} while (0)
#else // !(defined(WEBP_USE_THREAD) && !defined(_WIN32))
#define LOCK_ACCESS do {} while (0)
#define UNLOCK_ACCESS_AND_RETURN return
#endif // defined(WEBP_USE_THREAD) && !defined(_WIN32)
// Hidden exported init function. // Hidden exported init function.
// By default SharpYuvConvert calls it with NULL. If needed, users can declare // By default SharpYuvConvert calls it with SharpYuvGetCPUInfo. If needed,
// it as extern and call it with a VP8CPUInfo function. // users can declare it as extern and call it with an alternate VP8CPUInfo
extern void SharpYuvInit(VP8CPUInfo cpu_info_func); // function.
SHARPYUV_EXTERN void SharpYuvInit(VP8CPUInfo cpu_info_func);
void SharpYuvInit(VP8CPUInfo cpu_info_func) { void SharpYuvInit(VP8CPUInfo cpu_info_func) {
static volatile VP8CPUInfo sharpyuv_last_cpuinfo_used = static volatile VP8CPUInfo sharpyuv_last_cpuinfo_used =
(VP8CPUInfo)&sharpyuv_last_cpuinfo_used; (VP8CPUInfo)&sharpyuv_last_cpuinfo_used;
const int initialized = LOCK_ACCESS;
(sharpyuv_last_cpuinfo_used != (VP8CPUInfo)&sharpyuv_last_cpuinfo_used); // Only update SharpYuvGetCPUInfo when called from external code to avoid a
if (cpu_info_func == NULL && initialized) return; // race on reading the value in SharpYuvConvert().
if (sharpyuv_last_cpuinfo_used == cpu_info_func) return; if (cpu_info_func != (VP8CPUInfo)&SharpYuvGetCPUInfo) {
SharpYuvGetCPUInfo = cpu_info_func;
SharpYuvInitDsp(cpu_info_func); }
if (!initialized) { if (sharpyuv_last_cpuinfo_used == SharpYuvGetCPUInfo) {
SharpYuvInitGammaTables(); UNLOCK_ACCESS_AND_RETURN;
} }
sharpyuv_last_cpuinfo_used = cpu_info_func; SharpYuvInitDsp();
SharpYuvInitGammaTables();
sharpyuv_last_cpuinfo_used = SharpYuvGetCPUInfo;
UNLOCK_ACCESS_AND_RETURN;
} }
int SharpYuvConvert(const void* r_ptr, const void* g_ptr, int SharpYuvConvert(const void* r_ptr, const void* g_ptr,
@ -467,7 +494,8 @@ int SharpYuvConvert(const void* r_ptr, const void* g_ptr,
// Stride should be even for uint16_t buffers. // Stride should be even for uint16_t buffers.
return 0; return 0;
} }
SharpYuvInit(NULL); // The address of the function pointer is used to avoid a read race.
SharpYuvInit((VP8CPUInfo)&SharpYuvGetCPUInfo);
// Add scaling factor to go from rgb_bit_depth to yuv_bit_depth, to the // Add scaling factor to go from rgb_bit_depth to yuv_bit_depth, to the
// rgb->yuv conversion matrix. // rgb->yuv conversion matrix.

View file

@ -12,15 +12,31 @@
#ifndef WEBP_SHARPYUV_SHARPYUV_H_ #ifndef WEBP_SHARPYUV_SHARPYUV_H_
#define WEBP_SHARPYUV_SHARPYUV_H_ #define WEBP_SHARPYUV_SHARPYUV_H_
#include <inttypes.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#ifndef SHARPYUV_EXTERN
#ifdef WEBP_EXTERN
#define SHARPYUV_EXTERN WEBP_EXTERN
#else
// This explicitly marks library functions and allows for changing the
// signature for e.g., Windows DLL builds.
#if defined(__GNUC__) && __GNUC__ >= 4
#define SHARPYUV_EXTERN extern __attribute__((visibility("default")))
#else
#if defined(_MSC_VER) && defined(WEBP_DLL)
#define SHARPYUV_EXTERN __declspec(dllexport)
#else
#define SHARPYUV_EXTERN extern
#endif /* _MSC_VER && WEBP_DLL */
#endif /* __GNUC__ >= 4 */
#endif /* WEBP_EXTERN */
#endif /* SHARPYUV_EXTERN */
// SharpYUV API version following the convention from semver.org // SharpYUV API version following the convention from semver.org
#define SHARPYUV_VERSION_MAJOR 0 #define SHARPYUV_VERSION_MAJOR 0
#define SHARPYUV_VERSION_MINOR 1 #define SHARPYUV_VERSION_MINOR 2
#define SHARPYUV_VERSION_PATCH 0 #define SHARPYUV_VERSION_PATCH 0
// Version as a uint32_t. The major number is the high 8 bits. // Version as a uint32_t. The major number is the high 8 bits.
// The minor number is the middle 8 bits. The patch number is the low 16 bits. // The minor number is the middle 8 bits. The patch number is the low 16 bits.
@ -30,6 +46,10 @@ extern "C" {
SHARPYUV_MAKE_VERSION(SHARPYUV_VERSION_MAJOR, SHARPYUV_VERSION_MINOR, \ SHARPYUV_MAKE_VERSION(SHARPYUV_VERSION_MAJOR, SHARPYUV_VERSION_MINOR, \
SHARPYUV_VERSION_PATCH) SHARPYUV_VERSION_PATCH)
// Returns the library's version number, packed in hexadecimal. See
// SHARPYUV_VERSION.
SHARPYUV_EXTERN int SharpYuvGetVersion(void);
// RGB to YUV conversion matrix, in 16 bit fixed point. // RGB to YUV conversion matrix, in 16 bit fixed point.
// y = rgb_to_y[0] * r + rgb_to_y[1] * g + rgb_to_y[2] * b + rgb_to_y[3] // y = rgb_to_y[0] * r + rgb_to_y[1] * g + rgb_to_y[2] * b + rgb_to_y[3]
// u = rgb_to_u[0] * r + rgb_to_u[1] * g + rgb_to_u[2] * b + rgb_to_u[3] // u = rgb_to_u[0] * r + rgb_to_u[1] * g + rgb_to_u[2] * b + rgb_to_u[3]
@ -65,11 +85,13 @@ typedef struct {
// adjacent pixels on the y, u and v channels. If yuv_bit_depth > 8, they // adjacent pixels on the y, u and v channels. If yuv_bit_depth > 8, they
// should be multiples of 2. // should be multiples of 2.
// width, height: width and height of the image in pixels // width, height: width and height of the image in pixels
int SharpYuvConvert(const void* r_ptr, const void* g_ptr, const void* b_ptr, SHARPYUV_EXTERN int SharpYuvConvert(const void* r_ptr, const void* g_ptr,
int rgb_step, int rgb_stride, int rgb_bit_depth, const void* b_ptr, int rgb_step,
void* y_ptr, int y_stride, void* u_ptr, int u_stride, int rgb_stride, int rgb_bit_depth,
void* v_ptr, int v_stride, int yuv_bit_depth, int width, void* y_ptr, int y_stride, void* u_ptr,
int height, const SharpYuvConversionMatrix* yuv_matrix); int u_stride, void* v_ptr, int v_stride,
int yuv_bit_depth, int width, int height,
const SharpYuvConversionMatrix* yuv_matrix);
// TODO(b/194336375): Add YUV444 to YUV420 conversion. Maybe also add 422 // TODO(b/194336375): Add YUV444 to YUV420 conversion. Maybe also add 422
// support (it's rarely used in practice, especially for images). // support (it's rarely used in practice, especially for images).

View file

@ -0,0 +1,14 @@
// Copyright 2022 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.
// -----------------------------------------------------------------------------
//
#include "sharpyuv/sharpyuv_cpu.h"
// Include src/dsp/cpu.c to create SharpYuvGetCPUInfo from VP8GetCPUInfo. The
// function pointer is renamed in sharpyuv_cpu.h.
#include "src/dsp/cpu.c"

View file

@ -0,0 +1,22 @@
// Copyright 2022 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.
// -----------------------------------------------------------------------------
//
#ifndef WEBP_SHARPYUV_SHARPYUV_CPU_H_
#define WEBP_SHARPYUV_SHARPYUV_CPU_H_
#include "sharpyuv/sharpyuv.h"
// Avoid exporting SharpYuvGetCPUInfo in shared object / DLL builds.
// SharpYuvInit() replaces the use of the function pointer.
#undef WEBP_EXTERN
#define WEBP_EXTERN extern
#define VP8GetCPUInfo SharpYuvGetCPUInfo
#include "src/dsp/cpu.h"
#endif // WEBP_SHARPYUV_SHARPYUV_CPU_H_

View file

@ -13,7 +13,7 @@
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
#include <string.h> #include <stddef.h>
static int ToFixed16(float f) { return (int)floor(f * (1 << 16) + 0.5f); } static int ToFixed16(float f) { return (int)floor(f * (1 << 16) + 0.5f); }

View file

@ -35,8 +35,9 @@ typedef struct {
} SharpYuvColorSpace; } SharpYuvColorSpace;
// Fills in 'matrix' for the given YUVColorSpace. // Fills in 'matrix' for the given YUVColorSpace.
void SharpYuvComputeConversionMatrix(const SharpYuvColorSpace* yuv_color_space, SHARPYUV_EXTERN void SharpYuvComputeConversionMatrix(
SharpYuvConversionMatrix* matrix); const SharpYuvColorSpace* yuv_color_space,
SharpYuvConversionMatrix* matrix);
// Enums for precomputed conversion matrices. // Enums for precomputed conversion matrices.
typedef enum { typedef enum {
@ -49,7 +50,7 @@ typedef enum {
} SharpYuvMatrixType; } SharpYuvMatrixType;
// Returns a pointer to a matrix for one of the predefined colorspaces. // Returns a pointer to a matrix for one of the predefined colorspaces.
const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix( SHARPYUV_EXTERN const SharpYuvConversionMatrix* SharpYuvGetConversionMatrix(
SharpYuvMatrixType matrix_type); SharpYuvMatrixType matrix_type);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -16,7 +16,7 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include "src/dsp/cpu.h" #include "sharpyuv/sharpyuv_cpu.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -75,23 +75,24 @@ void (*SharpYuvFilterRow)(const int16_t* A, const int16_t* B, int len,
extern void InitSharpYuvSSE2(void); extern void InitSharpYuvSSE2(void);
extern void InitSharpYuvNEON(void); extern void InitSharpYuvNEON(void);
void SharpYuvInitDsp(VP8CPUInfo cpu_info_func) { void SharpYuvInitDsp(void) {
(void)cpu_info_func;
#if !WEBP_NEON_OMIT_C_CODE #if !WEBP_NEON_OMIT_C_CODE
SharpYuvUpdateY = SharpYuvUpdateY_C; SharpYuvUpdateY = SharpYuvUpdateY_C;
SharpYuvUpdateRGB = SharpYuvUpdateRGB_C; SharpYuvUpdateRGB = SharpYuvUpdateRGB_C;
SharpYuvFilterRow = SharpYuvFilterRow_C; SharpYuvFilterRow = SharpYuvFilterRow_C;
#endif #endif
if (SharpYuvGetCPUInfo != NULL) {
#if defined(WEBP_HAVE_SSE2) #if defined(WEBP_HAVE_SSE2)
if (cpu_info_func == NULL || cpu_info_func(kSSE2)) { if (SharpYuvGetCPUInfo(kSSE2)) {
InitSharpYuvSSE2(); InitSharpYuvSSE2();
} }
#endif // WEBP_HAVE_SSE2 #endif // WEBP_HAVE_SSE2
}
#if defined(WEBP_HAVE_NEON) #if defined(WEBP_HAVE_NEON)
if (WEBP_NEON_OMIT_C_CODE || cpu_info_func == NULL || cpu_info_func(kNEON)) { if (WEBP_NEON_OMIT_C_CODE ||
(SharpYuvGetCPUInfo != NULL && SharpYuvGetCPUInfo(kNEON))) {
InitSharpYuvNEON(); InitSharpYuvNEON();
} }
#endif // WEBP_HAVE_NEON #endif // WEBP_HAVE_NEON

View file

@ -12,9 +12,8 @@
#ifndef WEBP_SHARPYUV_SHARPYUV_DSP_H_ #ifndef WEBP_SHARPYUV_SHARPYUV_DSP_H_
#define WEBP_SHARPYUV_SHARPYUV_DSP_H_ #define WEBP_SHARPYUV_SHARPYUV_DSP_H_
#include <stdint.h> #include "sharpyuv/sharpyuv_cpu.h"
#include "src/webp/types.h"
#include "src/dsp/cpu.h"
extern uint64_t (*SharpYuvUpdateY)(const uint16_t* src, const uint16_t* ref, extern uint64_t (*SharpYuvUpdateY)(const uint16_t* src, const uint16_t* ref,
uint16_t* dst, int len, int bit_depth); uint16_t* dst, int len, int bit_depth);
@ -24,6 +23,6 @@ extern void (*SharpYuvFilterRow)(const int16_t* A, const int16_t* B, int len,
const uint16_t* best_y, uint16_t* out, const uint16_t* best_y, uint16_t* out,
int bit_depth); int bit_depth);
void SharpYuvInitDsp(VP8CPUInfo cpu_info_func); void SharpYuvInitDsp(void);
#endif // WEBP_SHARPYUV_SHARPYUV_DSP_H_ #endif // WEBP_SHARPYUV_SHARPYUV_DSP_H_

View file

@ -13,7 +13,6 @@
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
#include <stdint.h>
#include "src/webp/types.h" #include "src/webp/types.h"

View file

@ -12,7 +12,7 @@
#ifndef WEBP_SHARPYUV_SHARPYUV_GAMMA_H_ #ifndef WEBP_SHARPYUV_SHARPYUV_GAMMA_H_
#define WEBP_SHARPYUV_SHARPYUV_GAMMA_H_ #define WEBP_SHARPYUV_SHARPYUV_GAMMA_H_
#include <stdint.h> #include "src/webp/types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View file

@ -17,11 +17,6 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <arm_neon.h> #include <arm_neon.h>
#endif
extern void InitSharpYuvNEON(void);
#if defined(WEBP_USE_NEON)
static uint16_t clip_NEON(int v, int max) { static uint16_t clip_NEON(int v, int max) {
return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v; return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v;
@ -169,6 +164,8 @@ static void SharpYuvFilterRow_NEON(const int16_t* A, const int16_t* B, int len,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
extern void InitSharpYuvNEON(void);
WEBP_TSAN_IGNORE_FUNCTION void InitSharpYuvNEON(void) { WEBP_TSAN_IGNORE_FUNCTION void InitSharpYuvNEON(void) {
SharpYuvUpdateY = SharpYuvUpdateY_NEON; SharpYuvUpdateY = SharpYuvUpdateY_NEON;
SharpYuvUpdateRGB = SharpYuvUpdateRGB_NEON; SharpYuvUpdateRGB = SharpYuvUpdateRGB_NEON;
@ -177,6 +174,8 @@ WEBP_TSAN_IGNORE_FUNCTION void InitSharpYuvNEON(void) {
#else // !WEBP_USE_NEON #else // !WEBP_USE_NEON
extern void InitSharpYuvNEON(void);
void InitSharpYuvNEON(void) {} void InitSharpYuvNEON(void) {}
#endif // WEBP_USE_NEON #endif // WEBP_USE_NEON

View file

@ -16,11 +16,6 @@
#if defined(WEBP_USE_SSE2) #if defined(WEBP_USE_SSE2)
#include <stdlib.h> #include <stdlib.h>
#include <emmintrin.h> #include <emmintrin.h>
#endif
extern void InitSharpYuvSSE2(void);
#if defined(WEBP_USE_SSE2)
static uint16_t clip_SSE2(int v, int max) { static uint16_t clip_SSE2(int v, int max) {
return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v; return (v < 0) ? 0 : (v > max) ? max : (uint16_t)v;
@ -199,6 +194,8 @@ WEBP_TSAN_IGNORE_FUNCTION void InitSharpYuvSSE2(void) {
} }
#else // !WEBP_USE_SSE2 #else // !WEBP_USE_SSE2
extern void InitSharpYuvSSE2(void);
void InitSharpYuvSSE2(void) {} void InitSharpYuvSSE2(void) {}
#endif // WEBP_USE_SSE2 #endif // WEBP_USE_SSE2

View file

@ -31,8 +31,8 @@ extern "C" {
// version numbers // version numbers
#define DEC_MAJ_VERSION 1 #define DEC_MAJ_VERSION 1
#define DEC_MIN_VERSION 2 #define DEC_MIN_VERSION 3
#define DEC_REV_VERSION 4 #define DEC_REV_VERSION 0
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). // YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
// Constraints are: We need to store one 16x16 block of luma samples (y), // Constraints are: We need to store one 16x16 block of luma samples (y),

View file

@ -1336,7 +1336,7 @@ static int ReadTransform(int* const xsize, int const* ysize,
ok = ok && ExpandColorMap(num_colors, transform); ok = ok && ExpandColorMap(num_colors, transform);
break; break;
} }
case SUBTRACT_GREEN: case SUBTRACT_GREEN_TRANSFORM:
break; break;
default: default:
assert(0); // can't happen assert(0); // can't happen

View file

@ -179,7 +179,7 @@ static VP8StatusCode ParseOptionalChunks(const uint8_t** const data,
return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size.
} }
// For odd-sized chunk-payload, there's one byte padding at the end. // For odd-sized chunk-payload, there's one byte padding at the end.
disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1; disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1u;
total_size += disk_chunk_size; total_size += disk_chunk_size;
// Check that total bytes skipped so far does not exceed riff_size. // Check that total bytes skipped so far does not exceed riff_size.

View file

@ -24,8 +24,8 @@
#include "src/webp/format_constants.h" #include "src/webp/format_constants.h"
#define DMUX_MAJ_VERSION 1 #define DMUX_MAJ_VERSION 1
#define DMUX_MIN_VERSION 2 #define DMUX_MIN_VERSION 3
#define DMUX_REV_VERSION 4 #define DMUX_REV_VERSION 0
typedef struct { typedef struct {
size_t start_; // start location of the data size_t start_; // start location of the data

View file

@ -26,8 +26,8 @@ static int DispatchAlpha_SSE2(const uint8_t* WEBP_RESTRICT alpha,
uint32_t alpha_and = 0xff; uint32_t alpha_and = 0xff;
int i, j; int i, j;
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
const __m128i rgb_mask = _mm_set1_epi32(0xffffff00u); // to preserve RGB const __m128i rgb_mask = _mm_set1_epi32((int)0xffffff00); // to preserve RGB
const __m128i all_0xff = _mm_set_epi32(0, 0, ~0u, ~0u); const __m128i all_0xff = _mm_set_epi32(0, 0, ~0, ~0);
__m128i all_alphas = all_0xff; __m128i all_alphas = all_0xff;
// We must be able to access 3 extra bytes after the last written byte // We must be able to access 3 extra bytes after the last written byte
@ -106,8 +106,8 @@ static int ExtractAlpha_SSE2(const uint8_t* WEBP_RESTRICT argb, int argb_stride,
// value is not 0xff if any of the alpha[] is not equal to 0xff. // value is not 0xff if any of the alpha[] is not equal to 0xff.
uint32_t alpha_and = 0xff; uint32_t alpha_and = 0xff;
int i, j; int i, j;
const __m128i a_mask = _mm_set1_epi32(0xffu); // to preserve alpha const __m128i a_mask = _mm_set1_epi32(0xff); // to preserve alpha
const __m128i all_0xff = _mm_set_epi32(0, 0, ~0u, ~0u); const __m128i all_0xff = _mm_set_epi32(0, 0, ~0, ~0);
__m128i all_alphas = all_0xff; __m128i all_alphas = all_0xff;
// We must be able to access 3 extra bytes after the last written byte // We must be able to access 3 extra bytes after the last written byte
@ -178,7 +178,7 @@ static int ExtractAlpha_SSE2(const uint8_t* WEBP_RESTRICT argb, int argb_stride,
static void ApplyAlphaMultiply_SSE2(uint8_t* rgba, int alpha_first, static void ApplyAlphaMultiply_SSE2(uint8_t* rgba, int alpha_first,
int w, int h, int stride) { int w, int h, int stride) {
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
const __m128i kMult = _mm_set1_epi16(0x8081u); const __m128i kMult = _mm_set1_epi16((short)0x8081);
const __m128i kMask = _mm_set_epi16(0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0); const __m128i kMask = _mm_set_epi16(0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0);
const int kSpan = 4; const int kSpan = 4;
while (h-- > 0) { while (h-- > 0) {
@ -267,7 +267,7 @@ static int HasAlpha32b_SSE2(const uint8_t* src, int length) {
} }
static void AlphaReplace_SSE2(uint32_t* src, int length, uint32_t color) { static void AlphaReplace_SSE2(uint32_t* src, int length, uint32_t color) {
const __m128i m_color = _mm_set1_epi32(color); const __m128i m_color = _mm_set1_epi32((int)color);
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
int i = 0; int i = 0;
for (; i + 8 <= length; i += 8) { for (; i + 8 <= length; i += 8) {

View file

@ -26,7 +26,7 @@ static int ExtractAlpha_SSE41(const uint8_t* WEBP_RESTRICT argb,
// value is not 0xff if any of the alpha[] is not equal to 0xff. // value is not 0xff if any of the alpha[] is not equal to 0xff.
uint32_t alpha_and = 0xff; uint32_t alpha_and = 0xff;
int i, j; int i, j;
const __m128i all_0xff = _mm_set1_epi32(~0u); const __m128i all_0xff = _mm_set1_epi32(~0);
__m128i all_alphas = all_0xff; __m128i all_alphas = all_0xff;
// We must be able to access 3 extra bytes after the last written byte // We must be able to access 3 extra bytes after the last written byte

View file

@ -212,7 +212,7 @@ VP8CPUInfo VP8GetCPUInfo = wasmCPUInfo;
#elif defined(WEBP_HAVE_NEON) #elif defined(WEBP_HAVE_NEON)
// In most cases this function doesn't check for NEON support (it's assumed by // In most cases this function doesn't check for NEON support (it's assumed by
// the configuration), but enables turning off NEON at runtime, for testing // the configuration), but enables turning off NEON at runtime, for testing
// purposes, by setting VP8DecGetCPUInfo = NULL. // purposes, by setting VP8GetCPUInfo = NULL.
static int armCPUInfo(CPUFeature feature) { static int armCPUInfo(CPUFeature feature) {
if (feature != kNEON) return 0; if (feature != kNEON) return 0;
#if defined(__linux__) && defined(WEBP_HAVE_NEON_RTCD) #if defined(__linux__) && defined(WEBP_HAVE_NEON_RTCD)

View file

@ -14,6 +14,8 @@
#ifndef WEBP_DSP_CPU_H_ #ifndef WEBP_DSP_CPU_H_
#define WEBP_DSP_CPU_H_ #define WEBP_DSP_CPU_H_
#include <stddef.h>
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "src/webp/config.h" #include "src/webp/config.h"
#endif #endif

View file

@ -158,10 +158,10 @@ static void Transform_SSE2(const int16_t* in, uint8_t* dst, int do_two) {
dst3 = _mm_loadl_epi64((__m128i*)(dst + 3 * BPS)); dst3 = _mm_loadl_epi64((__m128i*)(dst + 3 * BPS));
} else { } else {
// Load four bytes/pixels per line. // Load four bytes/pixels per line.
dst0 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 0 * BPS)); dst0 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 0 * BPS));
dst1 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 1 * BPS)); dst1 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 1 * BPS));
dst2 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 2 * BPS)); dst2 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 2 * BPS));
dst3 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 3 * BPS)); dst3 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 3 * BPS));
} }
// Convert to 16b. // Convert to 16b.
dst0 = _mm_unpacklo_epi8(dst0, zero); dst0 = _mm_unpacklo_epi8(dst0, zero);
@ -187,10 +187,10 @@ static void Transform_SSE2(const int16_t* in, uint8_t* dst, int do_two) {
_mm_storel_epi64((__m128i*)(dst + 3 * BPS), dst3); _mm_storel_epi64((__m128i*)(dst + 3 * BPS), dst3);
} else { } else {
// Store four bytes/pixels per line. // Store four bytes/pixels per line.
WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0)); WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0));
WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1)); WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1));
WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2)); WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2));
WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3)); WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3));
} }
} }
} }
@ -213,10 +213,10 @@ static void TransformAC3(const int16_t* in, uint8_t* dst) {
const __m128i m3 = _mm_subs_epi16(B, d4); const __m128i m3 = _mm_subs_epi16(B, d4);
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
// Load the source pixels. // Load the source pixels.
__m128i dst0 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 0 * BPS)); __m128i dst0 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 0 * BPS));
__m128i dst1 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 1 * BPS)); __m128i dst1 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 1 * BPS));
__m128i dst2 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 2 * BPS)); __m128i dst2 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 2 * BPS));
__m128i dst3 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 3 * BPS)); __m128i dst3 = _mm_cvtsi32_si128(WebPMemToInt32(dst + 3 * BPS));
// Convert to 16b. // Convert to 16b.
dst0 = _mm_unpacklo_epi8(dst0, zero); dst0 = _mm_unpacklo_epi8(dst0, zero);
dst1 = _mm_unpacklo_epi8(dst1, zero); dst1 = _mm_unpacklo_epi8(dst1, zero);
@ -233,10 +233,10 @@ static void TransformAC3(const int16_t* in, uint8_t* dst) {
dst2 = _mm_packus_epi16(dst2, dst2); dst2 = _mm_packus_epi16(dst2, dst2);
dst3 = _mm_packus_epi16(dst3, dst3); dst3 = _mm_packus_epi16(dst3, dst3);
// Store the results. // Store the results.
WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0)); WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0));
WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1)); WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1));
WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2)); WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2));
WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3)); WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3));
} }
#undef MUL #undef MUL
#endif // USE_TRANSFORM_AC3 #endif // USE_TRANSFORM_AC3
@ -477,11 +477,11 @@ static WEBP_INLINE void Load8x4_SSE2(const uint8_t* const b, int stride,
// A0 = 63 62 61 60 23 22 21 20 43 42 41 40 03 02 01 00 // A0 = 63 62 61 60 23 22 21 20 43 42 41 40 03 02 01 00
// A1 = 73 72 71 70 33 32 31 30 53 52 51 50 13 12 11 10 // A1 = 73 72 71 70 33 32 31 30 53 52 51 50 13 12 11 10
const __m128i A0 = _mm_set_epi32( const __m128i A0 = _mm_set_epi32(
WebPMemToUint32(&b[6 * stride]), WebPMemToUint32(&b[2 * stride]), WebPMemToInt32(&b[6 * stride]), WebPMemToInt32(&b[2 * stride]),
WebPMemToUint32(&b[4 * stride]), WebPMemToUint32(&b[0 * stride])); WebPMemToInt32(&b[4 * stride]), WebPMemToInt32(&b[0 * stride]));
const __m128i A1 = _mm_set_epi32( const __m128i A1 = _mm_set_epi32(
WebPMemToUint32(&b[7 * stride]), WebPMemToUint32(&b[3 * stride]), WebPMemToInt32(&b[7 * stride]), WebPMemToInt32(&b[3 * stride]),
WebPMemToUint32(&b[5 * stride]), WebPMemToUint32(&b[1 * stride])); WebPMemToInt32(&b[5 * stride]), WebPMemToInt32(&b[1 * stride]));
// B0 = 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00 // B0 = 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00
// B1 = 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20 // B1 = 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20
@ -540,7 +540,7 @@ static WEBP_INLINE void Store4x4_SSE2(__m128i* const x,
uint8_t* dst, int stride) { uint8_t* dst, int stride) {
int i; int i;
for (i = 0; i < 4; ++i, dst += stride) { for (i = 0; i < 4; ++i, dst += stride) {
WebPUint32ToMem(dst, _mm_cvtsi128_si32(*x)); WebPInt32ToMem(dst, _mm_cvtsi128_si32(*x));
*x = _mm_srli_si128(*x, 4); *x = _mm_srli_si128(*x, 4);
} }
} }
@ -908,10 +908,10 @@ static void VE4_SSE2(uint8_t* dst) { // vertical
const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one); const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one);
const __m128i b = _mm_subs_epu8(a, lsb); const __m128i b = _mm_subs_epu8(a, lsb);
const __m128i avg = _mm_avg_epu8(b, BCDEFGH0); const __m128i avg = _mm_avg_epu8(b, BCDEFGH0);
const uint32_t vals = _mm_cvtsi128_si32(avg); const int vals = _mm_cvtsi128_si32(avg);
int i; int i;
for (i = 0; i < 4; ++i) { for (i = 0; i < 4; ++i) {
WebPUint32ToMem(dst + i * BPS, vals); WebPInt32ToMem(dst + i * BPS, vals);
} }
} }
@ -925,10 +925,10 @@ static void LD4_SSE2(uint8_t* dst) { // Down-Left
const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one); const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one);
const __m128i avg2 = _mm_subs_epu8(avg1, lsb); const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0); const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0);
WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg )); WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg ));
WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
} }
static void VR4_SSE2(uint8_t* dst) { // Vertical-Right static void VR4_SSE2(uint8_t* dst) { // Vertical-Right
@ -946,10 +946,10 @@ static void VR4_SSE2(uint8_t* dst) { // Vertical-Right
const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one); const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
const __m128i avg2 = _mm_subs_epu8(avg1, lsb); const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
const __m128i efgh = _mm_avg_epu8(avg2, XABCD); const __m128i efgh = _mm_avg_epu8(avg2, XABCD);
WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd )); WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd ));
WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh )); WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh ));
WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1))); WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1)));
WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1))); WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1)));
// these two are hard to implement in SSE2, so we keep the C-version: // these two are hard to implement in SSE2, so we keep the C-version:
DST(0, 2) = AVG3(J, I, X); DST(0, 2) = AVG3(J, I, X);
@ -970,11 +970,12 @@ static void VL4_SSE2(uint8_t* dst) { // Vertical-Left
const __m128i abbc = _mm_or_si128(ab, bc); const __m128i abbc = _mm_or_si128(ab, bc);
const __m128i lsb2 = _mm_and_si128(abbc, lsb1); const __m128i lsb2 = _mm_and_si128(abbc, lsb1);
const __m128i avg4 = _mm_subs_epu8(avg3, lsb2); const __m128i avg4 = _mm_subs_epu8(avg3, lsb2);
const uint32_t extra_out = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 4)); const uint32_t extra_out =
WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 )); (uint32_t)_mm_cvtsi128_si32(_mm_srli_si128(avg4, 4));
WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 )); WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 ));
WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1))); WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 ));
WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1))); WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1)));
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1)));
// these two are hard to get and irregular // these two are hard to get and irregular
DST(3, 2) = (extra_out >> 0) & 0xff; DST(3, 2) = (extra_out >> 0) & 0xff;
@ -990,7 +991,7 @@ static void RD4_SSE2(uint8_t* dst) { // Down-right
const uint32_t K = dst[-1 + 2 * BPS]; const uint32_t K = dst[-1 + 2 * BPS];
const uint32_t L = dst[-1 + 3 * BPS]; const uint32_t L = dst[-1 + 3 * BPS];
const __m128i LKJI_____ = const __m128i LKJI_____ =
_mm_cvtsi32_si128(L | (K << 8) | (J << 16) | (I << 24)); _mm_cvtsi32_si128((int)(L | (K << 8) | (J << 16) | (I << 24)));
const __m128i LKJIXABCD = _mm_or_si128(LKJI_____, ____XABCD); const __m128i LKJIXABCD = _mm_or_si128(LKJI_____, ____XABCD);
const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1); const __m128i KJIXABCD_ = _mm_srli_si128(LKJIXABCD, 1);
const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2); const __m128i JIXABCD__ = _mm_srli_si128(LKJIXABCD, 2);
@ -998,10 +999,10 @@ static void RD4_SSE2(uint8_t* dst) { // Down-right
const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one); const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one);
const __m128i avg2 = _mm_subs_epu8(avg1, lsb); const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_); const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_);
WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg )); WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg ));
WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
} }
#undef DST #undef DST
@ -1015,13 +1016,13 @@ static WEBP_INLINE void TrueMotion_SSE2(uint8_t* dst, int size) {
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
int y; int y;
if (size == 4) { if (size == 4) {
const __m128i top_values = _mm_cvtsi32_si128(WebPMemToUint32(top)); const __m128i top_values = _mm_cvtsi32_si128(WebPMemToInt32(top));
const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); const __m128i top_base = _mm_unpacklo_epi8(top_values, zero);
for (y = 0; y < 4; ++y, dst += BPS) { for (y = 0; y < 4; ++y, dst += BPS) {
const int val = dst[-1] - top[-1]; const int val = dst[-1] - top[-1];
const __m128i base = _mm_set1_epi16(val); const __m128i base = _mm_set1_epi16(val);
const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero);
WebPUint32ToMem(dst, _mm_cvtsi128_si32(out)); WebPInt32ToMem(dst, _mm_cvtsi128_si32(out));
} }
} else if (size == 8) { } else if (size == 8) {
const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); const __m128i top_values = _mm_loadl_epi64((const __m128i*)top);
@ -1062,7 +1063,7 @@ static void VE16_SSE2(uint8_t* dst) {
static void HE16_SSE2(uint8_t* dst) { // horizontal static void HE16_SSE2(uint8_t* dst) { // horizontal
int j; int j;
for (j = 16; j > 0; --j) { for (j = 16; j > 0; --j) {
const __m128i values = _mm_set1_epi8(dst[-1]); const __m128i values = _mm_set1_epi8((char)dst[-1]);
_mm_storeu_si128((__m128i*)dst, values); _mm_storeu_si128((__m128i*)dst, values);
dst += BPS; dst += BPS;
} }
@ -1070,7 +1071,7 @@ static void HE16_SSE2(uint8_t* dst) { // horizontal
static WEBP_INLINE void Put16_SSE2(uint8_t v, uint8_t* dst) { static WEBP_INLINE void Put16_SSE2(uint8_t v, uint8_t* dst) {
int j; int j;
const __m128i values = _mm_set1_epi8(v); const __m128i values = _mm_set1_epi8((char)v);
for (j = 0; j < 16; ++j) { for (j = 0; j < 16; ++j) {
_mm_storeu_si128((__m128i*)(dst + j * BPS), values); _mm_storeu_si128((__m128i*)(dst + j * BPS), values);
} }
@ -1130,7 +1131,7 @@ static void VE8uv_SSE2(uint8_t* dst) { // vertical
// helper for chroma-DC predictions // helper for chroma-DC predictions
static WEBP_INLINE void Put8x8uv_SSE2(uint8_t v, uint8_t* dst) { static WEBP_INLINE void Put8x8uv_SSE2(uint8_t v, uint8_t* dst) {
int j; int j;
const __m128i values = _mm_set1_epi8(v); const __m128i values = _mm_set1_epi8((char)v);
for (j = 0; j < 8; ++j) { for (j = 0; j < 8; ++j) {
_mm_storel_epi64((__m128i*)(dst + j * BPS), values); _mm_storel_epi64((__m128i*)(dst + j * BPS), values);
} }

View file

@ -23,7 +23,7 @@ static void HE16_SSE41(uint8_t* dst) { // horizontal
int j; int j;
const __m128i kShuffle3 = _mm_set1_epi8(3); const __m128i kShuffle3 = _mm_set1_epi8(3);
for (j = 16; j > 0; --j) { for (j = 16; j > 0; --j) {
const __m128i in = _mm_cvtsi32_si128(WebPMemToUint32(dst - 4)); const __m128i in = _mm_cvtsi32_si128(WebPMemToInt32(dst - 4));
const __m128i values = _mm_shuffle_epi8(in, kShuffle3); const __m128i values = _mm_shuffle_epi8(in, kShuffle3);
_mm_storeu_si128((__m128i*)dst, values); _mm_storeu_si128((__m128i*)dst, values);
dst += BPS; dst += BPS;

View file

@ -764,9 +764,14 @@ static WEBP_INLINE void AccumulateSSE16_NEON(const uint8_t* const a,
// Horizontal sum of all four uint32_t values in 'sum'. // Horizontal sum of all four uint32_t values in 'sum'.
static int SumToInt_NEON(uint32x4_t sum) { static int SumToInt_NEON(uint32x4_t sum) {
#if defined(__aarch64__)
return (int)vaddvq_u32(sum);
#else
const uint64x2_t sum2 = vpaddlq_u32(sum); const uint64x2_t sum2 = vpaddlq_u32(sum);
const uint64_t sum3 = vgetq_lane_u64(sum2, 0) + vgetq_lane_u64(sum2, 1); const uint32x2_t sum3 = vadd_u32(vreinterpret_u32_u64(vget_low_u64(sum2)),
return (int)sum3; vreinterpret_u32_u64(vget_high_u64(sum2)));
return (int)vget_lane_u32(sum3, 0);
#endif
} }
static int SSE16x16_NEON(const uint8_t* a, const uint8_t* b) { static int SSE16x16_NEON(const uint8_t* a, const uint8_t* b) {

View file

@ -156,10 +156,10 @@ static void ITransform_SSE2(const uint8_t* ref, const int16_t* in, uint8_t* dst,
ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]); ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]);
} else { } else {
// Load four bytes/pixels per line. // Load four bytes/pixels per line.
ref0 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[0 * BPS])); ref0 = _mm_cvtsi32_si128(WebPMemToInt32(&ref[0 * BPS]));
ref1 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[1 * BPS])); ref1 = _mm_cvtsi32_si128(WebPMemToInt32(&ref[1 * BPS]));
ref2 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[2 * BPS])); ref2 = _mm_cvtsi32_si128(WebPMemToInt32(&ref[2 * BPS]));
ref3 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[3 * BPS])); ref3 = _mm_cvtsi32_si128(WebPMemToInt32(&ref[3 * BPS]));
} }
// Convert to 16b. // Convert to 16b.
ref0 = _mm_unpacklo_epi8(ref0, zero); ref0 = _mm_unpacklo_epi8(ref0, zero);
@ -185,10 +185,10 @@ static void ITransform_SSE2(const uint8_t* ref, const int16_t* in, uint8_t* dst,
_mm_storel_epi64((__m128i*)&dst[3 * BPS], ref3); _mm_storel_epi64((__m128i*)&dst[3 * BPS], ref3);
} else { } else {
// Store four bytes/pixels per line. // Store four bytes/pixels per line.
WebPUint32ToMem(&dst[0 * BPS], _mm_cvtsi128_si32(ref0)); WebPInt32ToMem(&dst[0 * BPS], _mm_cvtsi128_si32(ref0));
WebPUint32ToMem(&dst[1 * BPS], _mm_cvtsi128_si32(ref1)); WebPInt32ToMem(&dst[1 * BPS], _mm_cvtsi128_si32(ref1));
WebPUint32ToMem(&dst[2 * BPS], _mm_cvtsi128_si32(ref2)); WebPInt32ToMem(&dst[2 * BPS], _mm_cvtsi128_si32(ref2));
WebPUint32ToMem(&dst[3 * BPS], _mm_cvtsi128_si32(ref3)); WebPInt32ToMem(&dst[3 * BPS], _mm_cvtsi128_si32(ref3));
} }
} }
} }
@ -481,7 +481,7 @@ static void CollectHistogram_SSE2(const uint8_t* ref, const uint8_t* pred,
// helper for chroma-DC predictions // helper for chroma-DC predictions
static WEBP_INLINE void Put8x8uv_SSE2(uint8_t v, uint8_t* dst) { static WEBP_INLINE void Put8x8uv_SSE2(uint8_t v, uint8_t* dst) {
int j; int j;
const __m128i values = _mm_set1_epi8(v); const __m128i values = _mm_set1_epi8((char)v);
for (j = 0; j < 8; ++j) { for (j = 0; j < 8; ++j) {
_mm_storel_epi64((__m128i*)(dst + j * BPS), values); _mm_storel_epi64((__m128i*)(dst + j * BPS), values);
} }
@ -489,7 +489,7 @@ static WEBP_INLINE void Put8x8uv_SSE2(uint8_t v, uint8_t* dst) {
static WEBP_INLINE void Put16_SSE2(uint8_t v, uint8_t* dst) { static WEBP_INLINE void Put16_SSE2(uint8_t v, uint8_t* dst) {
int j; int j;
const __m128i values = _mm_set1_epi8(v); const __m128i values = _mm_set1_epi8((char)v);
for (j = 0; j < 16; ++j) { for (j = 0; j < 16; ++j) {
_mm_store_si128((__m128i*)(dst + j * BPS), values); _mm_store_si128((__m128i*)(dst + j * BPS), values);
} }
@ -540,7 +540,7 @@ static WEBP_INLINE void VerticalPred_SSE2(uint8_t* dst,
static WEBP_INLINE void HE8uv_SSE2(uint8_t* dst, const uint8_t* left) { static WEBP_INLINE void HE8uv_SSE2(uint8_t* dst, const uint8_t* left) {
int j; int j;
for (j = 0; j < 8; ++j) { for (j = 0; j < 8; ++j) {
const __m128i values = _mm_set1_epi8(left[j]); const __m128i values = _mm_set1_epi8((char)left[j]);
_mm_storel_epi64((__m128i*)dst, values); _mm_storel_epi64((__m128i*)dst, values);
dst += BPS; dst += BPS;
} }
@ -549,7 +549,7 @@ static WEBP_INLINE void HE8uv_SSE2(uint8_t* dst, const uint8_t* left) {
static WEBP_INLINE void HE16_SSE2(uint8_t* dst, const uint8_t* left) { static WEBP_INLINE void HE16_SSE2(uint8_t* dst, const uint8_t* left) {
int j; int j;
for (j = 0; j < 16; ++j) { for (j = 0; j < 16; ++j) {
const __m128i values = _mm_set1_epi8(left[j]); const __m128i values = _mm_set1_epi8((char)left[j]);
_mm_store_si128((__m128i*)dst, values); _mm_store_si128((__m128i*)dst, values);
dst += BPS; dst += BPS;
} }
@ -722,10 +722,10 @@ static WEBP_INLINE void VE4_SSE2(uint8_t* dst,
const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one); const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGH00), one);
const __m128i b = _mm_subs_epu8(a, lsb); const __m128i b = _mm_subs_epu8(a, lsb);
const __m128i avg = _mm_avg_epu8(b, BCDEFGH0); const __m128i avg = _mm_avg_epu8(b, BCDEFGH0);
const uint32_t vals = _mm_cvtsi128_si32(avg); const int vals = _mm_cvtsi128_si32(avg);
int i; int i;
for (i = 0; i < 4; ++i) { for (i = 0; i < 4; ++i) {
WebPUint32ToMem(dst + i * BPS, vals); WebPInt32ToMem(dst + i * BPS, vals);
} }
} }
@ -760,10 +760,10 @@ static WEBP_INLINE void LD4_SSE2(uint8_t* dst,
const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one); const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one);
const __m128i avg2 = _mm_subs_epu8(avg1, lsb); const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0); const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0);
WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg )); WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg ));
WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
} }
static WEBP_INLINE void VR4_SSE2(uint8_t* dst, static WEBP_INLINE void VR4_SSE2(uint8_t* dst,
@ -782,10 +782,10 @@ static WEBP_INLINE void VR4_SSE2(uint8_t* dst,
const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one); const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one);
const __m128i avg2 = _mm_subs_epu8(avg1, lsb); const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
const __m128i efgh = _mm_avg_epu8(avg2, XABCD); const __m128i efgh = _mm_avg_epu8(avg2, XABCD);
WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd )); WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd ));
WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh )); WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh ));
WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1))); WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1)));
WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1))); WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1)));
// these two are hard to implement in SSE2, so we keep the C-version: // these two are hard to implement in SSE2, so we keep the C-version:
DST(0, 2) = AVG3(J, I, X); DST(0, 2) = AVG3(J, I, X);
@ -807,11 +807,12 @@ static WEBP_INLINE void VL4_SSE2(uint8_t* dst,
const __m128i abbc = _mm_or_si128(ab, bc); const __m128i abbc = _mm_or_si128(ab, bc);
const __m128i lsb2 = _mm_and_si128(abbc, lsb1); const __m128i lsb2 = _mm_and_si128(abbc, lsb1);
const __m128i avg4 = _mm_subs_epu8(avg3, lsb2); const __m128i avg4 = _mm_subs_epu8(avg3, lsb2);
const uint32_t extra_out = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 4)); const uint32_t extra_out =
WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 )); (uint32_t)_mm_cvtsi128_si32(_mm_srli_si128(avg4, 4));
WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 )); WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 ));
WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1))); WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 ));
WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1))); WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1)));
WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1)));
// these two are hard to get and irregular // these two are hard to get and irregular
DST(3, 2) = (extra_out >> 0) & 0xff; DST(3, 2) = (extra_out >> 0) & 0xff;
@ -829,10 +830,10 @@ static WEBP_INLINE void RD4_SSE2(uint8_t* dst,
const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one); const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one);
const __m128i avg2 = _mm_subs_epu8(avg1, lsb); const __m128i avg2 = _mm_subs_epu8(avg1, lsb);
const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_); const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_);
WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg )); WebPInt32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg ));
WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); WebPInt32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)));
WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); WebPInt32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)));
WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); WebPInt32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)));
} }
static WEBP_INLINE void HU4_SSE2(uint8_t* dst, const uint8_t* top) { static WEBP_INLINE void HU4_SSE2(uint8_t* dst, const uint8_t* top) {
@ -875,14 +876,14 @@ static WEBP_INLINE void HD4_SSE2(uint8_t* dst, const uint8_t* top) {
static WEBP_INLINE void TM4_SSE2(uint8_t* dst, const uint8_t* top) { static WEBP_INLINE void TM4_SSE2(uint8_t* dst, const uint8_t* top) {
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
const __m128i top_values = _mm_cvtsi32_si128(WebPMemToUint32(top)); const __m128i top_values = _mm_cvtsi32_si128(WebPMemToInt32(top));
const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); const __m128i top_base = _mm_unpacklo_epi8(top_values, zero);
int y; int y;
for (y = 0; y < 4; ++y, dst += BPS) { for (y = 0; y < 4; ++y, dst += BPS) {
const int val = top[-2 - y] - top[-1]; const int val = top[-2 - y] - top[-1];
const __m128i base = _mm_set1_epi16(val); const __m128i base = _mm_set1_epi16(val);
const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero);
WebPUint32ToMem(dst, _mm_cvtsi128_si32(out)); WebPInt32ToMem(dst, _mm_cvtsi128_si32(out));
} }
} }

View file

@ -49,7 +49,7 @@ static WEBP_INLINE uint32_t Clip255(uint32_t a) {
} }
static WEBP_INLINE int AddSubtractComponentFull(int a, int b, int c) { static WEBP_INLINE int AddSubtractComponentFull(int a, int b, int c) {
return Clip255(a + b - c); return Clip255((uint32_t)(a + b - c));
} }
static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
@ -66,7 +66,7 @@ static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
} }
static WEBP_INLINE int AddSubtractComponentHalf(int a, int b) { static WEBP_INLINE int AddSubtractComponentHalf(int a, int b) {
return Clip255(a + (a - b) / 2); return Clip255((uint32_t)(a + (a - b) / 2));
} }
static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
@ -293,10 +293,10 @@ void VP8LTransformColorInverse_C(const VP8LMultipliers* const m,
const uint32_t red = argb >> 16; const uint32_t red = argb >> 16;
int new_red = red & 0xff; int new_red = red & 0xff;
int new_blue = argb & 0xff; int new_blue = argb & 0xff;
new_red += ColorTransformDelta(m->green_to_red_, green); new_red += ColorTransformDelta((int8_t)m->green_to_red_, green);
new_red &= 0xff; new_red &= 0xff;
new_blue += ColorTransformDelta(m->green_to_blue_, green); new_blue += ColorTransformDelta((int8_t)m->green_to_blue_, green);
new_blue += ColorTransformDelta(m->red_to_blue_, (int8_t)new_red); new_blue += ColorTransformDelta((int8_t)m->red_to_blue_, (int8_t)new_red);
new_blue &= 0xff; new_blue &= 0xff;
dst[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); dst[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
} }
@ -395,7 +395,7 @@ void VP8LInverseTransform(const VP8LTransform* const transform,
assert(row_start < row_end); assert(row_start < row_end);
assert(row_end <= transform->ysize_); assert(row_end <= transform->ysize_);
switch (transform->type_) { switch (transform->type_) {
case SUBTRACT_GREEN: case SUBTRACT_GREEN_TRANSFORM:
VP8LAddGreenToBlueAndRed(in, (row_end - row_start) * width, out); VP8LAddGreenToBlueAndRed(in, (row_end - row_start) * width, out);
break; break;
case PREDICTOR_TRANSFORM: case PREDICTOR_TRANSFORM:

View file

@ -522,11 +522,11 @@ static void GetCombinedEntropyUnrefined_C(const uint32_t X[],
void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels) { void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels) {
int i; int i;
for (i = 0; i < num_pixels; ++i) { for (i = 0; i < num_pixels; ++i) {
const int argb = argb_data[i]; const int argb = (int)argb_data[i];
const int green = (argb >> 8) & 0xff; const int green = (argb >> 8) & 0xff;
const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff; const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff;
const uint32_t new_b = (((argb >> 0) & 0xff) - green) & 0xff; const uint32_t new_b = (((argb >> 0) & 0xff) - green) & 0xff;
argb_data[i] = (argb & 0xff00ff00u) | (new_r << 16) | new_b; argb_data[i] = ((uint32_t)argb & 0xff00ff00u) | (new_r << 16) | new_b;
} }
} }
@ -547,10 +547,10 @@ void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data,
const int8_t red = U32ToS8(argb >> 16); const int8_t red = U32ToS8(argb >> 16);
int new_red = red & 0xff; int new_red = red & 0xff;
int new_blue = argb & 0xff; int new_blue = argb & 0xff;
new_red -= ColorTransformDelta(m->green_to_red_, green); new_red -= ColorTransformDelta((int8_t)m->green_to_red_, green);
new_red &= 0xff; new_red &= 0xff;
new_blue -= ColorTransformDelta(m->green_to_blue_, green); new_blue -= ColorTransformDelta((int8_t)m->green_to_blue_, green);
new_blue -= ColorTransformDelta(m->red_to_blue_, red); new_blue -= ColorTransformDelta((int8_t)m->red_to_blue_, red);
new_blue &= 0xff; new_blue &= 0xff;
data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
} }
@ -560,7 +560,7 @@ static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red,
uint32_t argb) { uint32_t argb) {
const int8_t green = U32ToS8(argb >> 8); const int8_t green = U32ToS8(argb >> 8);
int new_red = argb >> 16; int new_red = argb >> 16;
new_red -= ColorTransformDelta(green_to_red, green); new_red -= ColorTransformDelta((int8_t)green_to_red, green);
return (new_red & 0xff); return (new_red & 0xff);
} }
@ -569,9 +569,9 @@ static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue,
uint32_t argb) { uint32_t argb) {
const int8_t green = U32ToS8(argb >> 8); const int8_t green = U32ToS8(argb >> 8);
const int8_t red = U32ToS8(argb >> 16); const int8_t red = U32ToS8(argb >> 16);
uint8_t new_blue = argb & 0xff; int new_blue = argb & 0xff;
new_blue -= ColorTransformDelta(green_to_blue, green); new_blue -= ColorTransformDelta((int8_t)green_to_blue, green);
new_blue -= ColorTransformDelta(red_to_blue, red); new_blue -= ColorTransformDelta((int8_t)red_to_blue, red);
return (new_blue & 0xff); return (new_blue & 0xff);
} }

View file

@ -54,8 +54,8 @@ static void TransformColor_SSE2(const VP8LMultipliers* const m,
const __m128i mults_rb = MK_CST_16(CST_5b(m->green_to_red_), const __m128i mults_rb = MK_CST_16(CST_5b(m->green_to_red_),
CST_5b(m->green_to_blue_)); CST_5b(m->green_to_blue_));
const __m128i mults_b2 = MK_CST_16(CST_5b(m->red_to_blue_), 0); const __m128i mults_b2 = MK_CST_16(CST_5b(m->red_to_blue_), 0);
const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks const __m128i mask_ag = _mm_set1_epi32((int)0xff00ff00); // alpha-green masks
const __m128i mask_rb = _mm_set1_epi32(0x00ff00ff); // red-blue masks const __m128i mask_rb = _mm_set1_epi32(0x00ff00ff); // red-blue masks
int i; int i;
for (i = 0; i + 4 <= num_pixels; i += 4) { for (i = 0; i + 4 <= num_pixels; i += 4) {
const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb
@ -376,7 +376,7 @@ static void BundleColorMap_SSE2(const uint8_t* const row, int width, int xbits,
break; break;
} }
case 2: { case 2: {
const __m128i mask_or = _mm_set1_epi32(0xff000000); const __m128i mask_or = _mm_set1_epi32((int)0xff000000);
const __m128i mul_cst = _mm_set1_epi16(0x0104); const __m128i mul_cst = _mm_set1_epi16(0x0104);
const __m128i mask_mul = _mm_set1_epi16(0x0f00); const __m128i mask_mul = _mm_set1_epi16(0x0f00);
for (x = 0; x + 16 <= width; x += 16, dst += 4) { for (x = 0; x + 16 <= width; x += 16, dst += 4) {
@ -427,7 +427,7 @@ static WEBP_INLINE void Average2_m128i(const __m128i* const a0,
static void PredictorSub0_SSE2(const uint32_t* in, const uint32_t* upper, static void PredictorSub0_SSE2(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) { int num_pixels, uint32_t* out) {
int i; int i;
const __m128i black = _mm_set1_epi32(ARGB_BLACK); const __m128i black = _mm_set1_epi32((int)ARGB_BLACK);
for (i = 0; i + 4 <= num_pixels; i += 4) { for (i = 0; i + 4 <= num_pixels; i += 4) {
const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]);
const __m128i res = _mm_sub_epi8(src, black); const __m128i res = _mm_sub_epi8(src, black);

View file

@ -27,23 +27,22 @@ static WEBP_INLINE uint32_t ClampedAddSubtractFull_SSE2(uint32_t c0,
uint32_t c1, uint32_t c1,
uint32_t c2) { uint32_t c2) {
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero); const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c0), zero);
const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero); const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c1), zero);
const __m128i C2 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c2), zero); const __m128i C2 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c2), zero);
const __m128i V1 = _mm_add_epi16(C0, C1); const __m128i V1 = _mm_add_epi16(C0, C1);
const __m128i V2 = _mm_sub_epi16(V1, C2); const __m128i V2 = _mm_sub_epi16(V1, C2);
const __m128i b = _mm_packus_epi16(V2, V2); const __m128i b = _mm_packus_epi16(V2, V2);
const uint32_t output = _mm_cvtsi128_si32(b); return (uint32_t)_mm_cvtsi128_si32(b);
return output;
} }
static WEBP_INLINE uint32_t ClampedAddSubtractHalf_SSE2(uint32_t c0, static WEBP_INLINE uint32_t ClampedAddSubtractHalf_SSE2(uint32_t c0,
uint32_t c1, uint32_t c1,
uint32_t c2) { uint32_t c2) {
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero); const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c0), zero);
const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero); const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c1), zero);
const __m128i B0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c2), zero); const __m128i B0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)c2), zero);
const __m128i avg = _mm_add_epi16(C1, C0); const __m128i avg = _mm_add_epi16(C1, C0);
const __m128i A0 = _mm_srli_epi16(avg, 1); const __m128i A0 = _mm_srli_epi16(avg, 1);
const __m128i A1 = _mm_sub_epi16(A0, B0); const __m128i A1 = _mm_sub_epi16(A0, B0);
@ -52,16 +51,15 @@ static WEBP_INLINE uint32_t ClampedAddSubtractHalf_SSE2(uint32_t c0,
const __m128i A3 = _mm_srai_epi16(A2, 1); const __m128i A3 = _mm_srai_epi16(A2, 1);
const __m128i A4 = _mm_add_epi16(A0, A3); const __m128i A4 = _mm_add_epi16(A0, A3);
const __m128i A5 = _mm_packus_epi16(A4, A4); const __m128i A5 = _mm_packus_epi16(A4, A4);
const uint32_t output = _mm_cvtsi128_si32(A5); return (uint32_t)_mm_cvtsi128_si32(A5);
return output;
} }
static WEBP_INLINE uint32_t Select_SSE2(uint32_t a, uint32_t b, uint32_t c) { static WEBP_INLINE uint32_t Select_SSE2(uint32_t a, uint32_t b, uint32_t c) {
int pa_minus_pb; int pa_minus_pb;
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
const __m128i A0 = _mm_cvtsi32_si128(a); const __m128i A0 = _mm_cvtsi32_si128((int)a);
const __m128i B0 = _mm_cvtsi32_si128(b); const __m128i B0 = _mm_cvtsi32_si128((int)b);
const __m128i C0 = _mm_cvtsi32_si128(c); const __m128i C0 = _mm_cvtsi32_si128((int)c);
const __m128i AC0 = _mm_subs_epu8(A0, C0); const __m128i AC0 = _mm_subs_epu8(A0, C0);
const __m128i CA0 = _mm_subs_epu8(C0, A0); const __m128i CA0 = _mm_subs_epu8(C0, A0);
const __m128i BC0 = _mm_subs_epu8(B0, C0); const __m128i BC0 = _mm_subs_epu8(B0, C0);
@ -94,8 +92,8 @@ static WEBP_INLINE void Average2_uint32_SSE2(const uint32_t a0,
__m128i* const avg) { __m128i* const avg) {
// (a + b) >> 1 = ((a + b + 1) >> 1) - ((a ^ b) & 1) // (a + b) >> 1 = ((a + b + 1) >> 1) - ((a ^ b) & 1)
const __m128i ones = _mm_set1_epi8(1); const __m128i ones = _mm_set1_epi8(1);
const __m128i A0 = _mm_cvtsi32_si128(a0); const __m128i A0 = _mm_cvtsi32_si128((int)a0);
const __m128i A1 = _mm_cvtsi32_si128(a1); const __m128i A1 = _mm_cvtsi32_si128((int)a1);
const __m128i avg1 = _mm_avg_epu8(A0, A1); const __m128i avg1 = _mm_avg_epu8(A0, A1);
const __m128i one = _mm_and_si128(_mm_xor_si128(A0, A1), ones); const __m128i one = _mm_and_si128(_mm_xor_si128(A0, A1), ones);
*avg = _mm_sub_epi8(avg1, one); *avg = _mm_sub_epi8(avg1, one);
@ -103,8 +101,8 @@ static WEBP_INLINE void Average2_uint32_SSE2(const uint32_t a0,
static WEBP_INLINE __m128i Average2_uint32_16_SSE2(uint32_t a0, uint32_t a1) { static WEBP_INLINE __m128i Average2_uint32_16_SSE2(uint32_t a0, uint32_t a1) {
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
const __m128i A0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a0), zero); const __m128i A0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)a0), zero);
const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a1), zero); const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)a1), zero);
const __m128i sum = _mm_add_epi16(A1, A0); const __m128i sum = _mm_add_epi16(A1, A0);
return _mm_srli_epi16(sum, 1); return _mm_srli_epi16(sum, 1);
} }
@ -112,19 +110,18 @@ static WEBP_INLINE __m128i Average2_uint32_16_SSE2(uint32_t a0, uint32_t a1) {
static WEBP_INLINE uint32_t Average2_SSE2(uint32_t a0, uint32_t a1) { static WEBP_INLINE uint32_t Average2_SSE2(uint32_t a0, uint32_t a1) {
__m128i output; __m128i output;
Average2_uint32_SSE2(a0, a1, &output); Average2_uint32_SSE2(a0, a1, &output);
return _mm_cvtsi128_si32(output); return (uint32_t)_mm_cvtsi128_si32(output);
} }
static WEBP_INLINE uint32_t Average3_SSE2(uint32_t a0, uint32_t a1, static WEBP_INLINE uint32_t Average3_SSE2(uint32_t a0, uint32_t a1,
uint32_t a2) { uint32_t a2) {
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
const __m128i avg1 = Average2_uint32_16_SSE2(a0, a2); const __m128i avg1 = Average2_uint32_16_SSE2(a0, a2);
const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a1), zero); const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128((int)a1), zero);
const __m128i sum = _mm_add_epi16(avg1, A1); const __m128i sum = _mm_add_epi16(avg1, A1);
const __m128i avg2 = _mm_srli_epi16(sum, 1); const __m128i avg2 = _mm_srli_epi16(sum, 1);
const __m128i A2 = _mm_packus_epi16(avg2, avg2); const __m128i A2 = _mm_packus_epi16(avg2, avg2);
const uint32_t output = _mm_cvtsi128_si32(A2); return (uint32_t)_mm_cvtsi128_si32(A2);
return output;
} }
static WEBP_INLINE uint32_t Average4_SSE2(uint32_t a0, uint32_t a1, static WEBP_INLINE uint32_t Average4_SSE2(uint32_t a0, uint32_t a1,
@ -134,8 +131,7 @@ static WEBP_INLINE uint32_t Average4_SSE2(uint32_t a0, uint32_t a1,
const __m128i sum = _mm_add_epi16(avg2, avg1); const __m128i sum = _mm_add_epi16(avg2, avg1);
const __m128i avg3 = _mm_srli_epi16(sum, 1); const __m128i avg3 = _mm_srli_epi16(sum, 1);
const __m128i A0 = _mm_packus_epi16(avg3, avg3); const __m128i A0 = _mm_packus_epi16(avg3, avg3);
const uint32_t output = _mm_cvtsi128_si32(A0); return (uint32_t)_mm_cvtsi128_si32(A0);
return output;
} }
static uint32_t Predictor5_SSE2(const uint32_t* const left, static uint32_t Predictor5_SSE2(const uint32_t* const left,
@ -192,7 +188,7 @@ static uint32_t Predictor13_SSE2(const uint32_t* const left,
static void PredictorAdd0_SSE2(const uint32_t* in, const uint32_t* upper, static void PredictorAdd0_SSE2(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) { int num_pixels, uint32_t* out) {
int i; int i;
const __m128i black = _mm_set1_epi32(ARGB_BLACK); const __m128i black = _mm_set1_epi32((int)ARGB_BLACK);
for (i = 0; i + 4 <= num_pixels; i += 4) { for (i = 0; i + 4 <= num_pixels; i += 4) {
const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]);
const __m128i res = _mm_add_epi8(src, black); const __m128i res = _mm_add_epi8(src, black);
@ -208,7 +204,7 @@ static void PredictorAdd0_SSE2(const uint32_t* in, const uint32_t* upper,
static void PredictorAdd1_SSE2(const uint32_t* in, const uint32_t* upper, static void PredictorAdd1_SSE2(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) { int num_pixels, uint32_t* out) {
int i; int i;
__m128i prev = _mm_set1_epi32(out[-1]); __m128i prev = _mm_set1_epi32((int)out[-1]);
for (i = 0; i + 4 <= num_pixels; i += 4) { for (i = 0; i + 4 <= num_pixels; i += 4) {
// a | b | c | d // a | b | c | d
const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]);
@ -285,12 +281,12 @@ GENERATE_PREDICTOR_2(9, upper[i + 1])
#undef GENERATE_PREDICTOR_2 #undef GENERATE_PREDICTOR_2
// Predictor10: average of (average of (L,TL), average of (T, TR)). // Predictor10: average of (average of (L,TL), average of (T, TR)).
#define DO_PRED10(OUT) do { \ #define DO_PRED10(OUT) do { \
__m128i avgLTL, avg; \ __m128i avgLTL, avg; \
Average2_m128i(&L, &TL, &avgLTL); \ Average2_m128i(&L, &TL, &avgLTL); \
Average2_m128i(&avgTTR, &avgLTL, &avg); \ Average2_m128i(&avgTTR, &avgLTL, &avg); \
L = _mm_add_epi8(avg, src); \ L = _mm_add_epi8(avg, src); \
out[i + (OUT)] = _mm_cvtsi128_si32(L); \ out[i + (OUT)] = (uint32_t)_mm_cvtsi128_si32(L); \
} while (0) } while (0)
#define DO_PRED10_SHIFT do { \ #define DO_PRED10_SHIFT do { \
@ -303,7 +299,7 @@ GENERATE_PREDICTOR_2(9, upper[i + 1])
static void PredictorAdd10_SSE2(const uint32_t* in, const uint32_t* upper, static void PredictorAdd10_SSE2(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) { int num_pixels, uint32_t* out) {
int i; int i;
__m128i L = _mm_cvtsi32_si128(out[-1]); __m128i L = _mm_cvtsi32_si128((int)out[-1]);
for (i = 0; i + 4 <= num_pixels; i += 4) { for (i = 0; i + 4 <= num_pixels; i += 4) {
__m128i src = _mm_loadu_si128((const __m128i*)&in[i]); __m128i src = _mm_loadu_si128((const __m128i*)&in[i]);
__m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]);
@ -336,7 +332,7 @@ static void PredictorAdd10_SSE2(const uint32_t* in, const uint32_t* upper,
const __m128i B = _mm_andnot_si128(mask, T); \ const __m128i B = _mm_andnot_si128(mask, T); \
const __m128i pred = _mm_or_si128(A, B); /* pred = (pa > b)? L : T*/ \ const __m128i pred = _mm_or_si128(A, B); /* pred = (pa > b)? L : T*/ \
L = _mm_add_epi8(src, pred); \ L = _mm_add_epi8(src, pred); \
out[i + (OUT)] = _mm_cvtsi128_si32(L); \ out[i + (OUT)] = (uint32_t)_mm_cvtsi128_si32(L); \
} while (0) } while (0)
#define DO_PRED11_SHIFT do { \ #define DO_PRED11_SHIFT do { \
@ -351,7 +347,7 @@ static void PredictorAdd11_SSE2(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) { int num_pixels, uint32_t* out) {
int i; int i;
__m128i pa; __m128i pa;
__m128i L = _mm_cvtsi32_si128(out[-1]); __m128i L = _mm_cvtsi32_si128((int)out[-1]);
for (i = 0; i + 4 <= num_pixels; i += 4) { for (i = 0; i + 4 <= num_pixels; i += 4) {
__m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]);
__m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]);
@ -384,12 +380,12 @@ static void PredictorAdd11_SSE2(const uint32_t* in, const uint32_t* upper,
#undef DO_PRED11_SHIFT #undef DO_PRED11_SHIFT
// Predictor12: ClampedAddSubtractFull. // Predictor12: ClampedAddSubtractFull.
#define DO_PRED12(DIFF, LANE, OUT) do { \ #define DO_PRED12(DIFF, LANE, OUT) do { \
const __m128i all = _mm_add_epi16(L, (DIFF)); \ const __m128i all = _mm_add_epi16(L, (DIFF)); \
const __m128i alls = _mm_packus_epi16(all, all); \ const __m128i alls = _mm_packus_epi16(all, all); \
const __m128i res = _mm_add_epi8(src, alls); \ const __m128i res = _mm_add_epi8(src, alls); \
out[i + (OUT)] = _mm_cvtsi128_si32(res); \ out[i + (OUT)] = (uint32_t)_mm_cvtsi128_si32(res); \
L = _mm_unpacklo_epi8(res, zero); \ L = _mm_unpacklo_epi8(res, zero); \
} while (0) } while (0)
#define DO_PRED12_SHIFT(DIFF, LANE) do { \ #define DO_PRED12_SHIFT(DIFF, LANE) do { \
@ -402,7 +398,7 @@ static void PredictorAdd12_SSE2(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) { int num_pixels, uint32_t* out) {
int i; int i;
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
const __m128i L8 = _mm_cvtsi32_si128(out[-1]); const __m128i L8 = _mm_cvtsi32_si128((int)out[-1]);
__m128i L = _mm_unpacklo_epi8(L8, zero); __m128i L = _mm_unpacklo_epi8(L8, zero);
for (i = 0; i + 4 <= num_pixels; i += 4) { for (i = 0; i + 4 <= num_pixels; i += 4) {
// Load 4 pixels at a time. // Load 4 pixels at a time.
@ -468,7 +464,7 @@ static void TransformColorInverse_SSE2(const VP8LMultipliers* const m,
const __m128i mults_b2 = MK_CST_16(CST(red_to_blue_), 0); const __m128i mults_b2 = MK_CST_16(CST(red_to_blue_), 0);
#undef MK_CST_16 #undef MK_CST_16
#undef CST #undef CST
const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); // alpha-green masks const __m128i mask_ag = _mm_set1_epi32((int)0xff00ff00); // alpha-green masks
int i; int i;
for (i = 0; i + 4 <= num_pixels; i += 4) { for (i = 0; i + 4 <= num_pixels; i += 4) {
const __m128i in = _mm_loadu_si128((const __m128i*)&src[i]); // argb const __m128i in = _mm_loadu_si128((const __m128i*)&src[i]); // argb
@ -532,7 +528,7 @@ static void ConvertBGRAToRGB_SSE2(const uint32_t* src, int num_pixels,
static void ConvertBGRAToRGBA_SSE2(const uint32_t* src, static void ConvertBGRAToRGBA_SSE2(const uint32_t* src,
int num_pixels, uint8_t* dst) { int num_pixels, uint8_t* dst) {
const __m128i red_blue_mask = _mm_set1_epi32(0x00ff00ffu); const __m128i red_blue_mask = _mm_set1_epi32(0x00ff00ff);
const __m128i* in = (const __m128i*)src; const __m128i* in = (const __m128i*)src;
__m128i* out = (__m128i*)dst; __m128i* out = (__m128i*)dst;
while (num_pixels >= 8) { while (num_pixels >= 8) {
@ -561,7 +557,7 @@ static void ConvertBGRAToRGBA_SSE2(const uint32_t* src,
static void ConvertBGRAToRGBA4444_SSE2(const uint32_t* src, static void ConvertBGRAToRGBA4444_SSE2(const uint32_t* src,
int num_pixels, uint8_t* dst) { int num_pixels, uint8_t* dst) {
const __m128i mask_0x0f = _mm_set1_epi8(0x0f); const __m128i mask_0x0f = _mm_set1_epi8(0x0f);
const __m128i mask_0xf0 = _mm_set1_epi8(0xf0); const __m128i mask_0xf0 = _mm_set1_epi8((char)0xf0);
const __m128i* in = (const __m128i*)src; const __m128i* in = (const __m128i*)src;
__m128i* out = (__m128i*)dst; __m128i* out = (__m128i*)dst;
while (num_pixels >= 8) { while (num_pixels >= 8) {
@ -596,8 +592,8 @@ static void ConvertBGRAToRGBA4444_SSE2(const uint32_t* src,
static void ConvertBGRAToRGB565_SSE2(const uint32_t* src, static void ConvertBGRAToRGB565_SSE2(const uint32_t* src,
int num_pixels, uint8_t* dst) { int num_pixels, uint8_t* dst) {
const __m128i mask_0xe0 = _mm_set1_epi8(0xe0); const __m128i mask_0xe0 = _mm_set1_epi8((char)0xe0);
const __m128i mask_0xf8 = _mm_set1_epi8(0xf8); const __m128i mask_0xf8 = _mm_set1_epi8((char)0xf8);
const __m128i mask_0x07 = _mm_set1_epi8(0x07); const __m128i mask_0x07 = _mm_set1_epi8(0x07);
const __m128i* in = (const __m128i*)src; const __m128i* in = (const __m128i*)src;
__m128i* out = (__m128i*)dst; __m128i* out = (__m128i*)dst;

View file

@ -25,11 +25,12 @@ static void TransformColorInverse_SSE41(const VP8LMultipliers* const m,
int num_pixels, uint32_t* dst) { int num_pixels, uint32_t* dst) {
// sign-extended multiplying constants, pre-shifted by 5. // sign-extended multiplying constants, pre-shifted by 5.
#define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend #define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend
const __m128i mults_rb = _mm_set1_epi32((uint32_t)CST(green_to_red_) << 16 | const __m128i mults_rb =
(CST(green_to_blue_) & 0xffff)); _mm_set1_epi32((int)((uint32_t)CST(green_to_red_) << 16 |
(CST(green_to_blue_) & 0xffff)));
const __m128i mults_b2 = _mm_set1_epi32(CST(red_to_blue_)); const __m128i mults_b2 = _mm_set1_epi32(CST(red_to_blue_));
#undef CST #undef CST
const __m128i mask_ag = _mm_set1_epi32(0xff00ff00); const __m128i mask_ag = _mm_set1_epi32((int)0xff00ff00);
const __m128i perm1 = _mm_setr_epi8(-1, 1, -1, 1, -1, 5, -1, 5, const __m128i perm1 = _mm_setr_epi8(-1, 1, -1, 1, -1, 5, -1, 5,
-1, 9, -1, 9, -1, 13, -1, 13); -1, 9, -1, 9, -1, 13, -1, 13);
const __m128i perm2 = _mm_setr_epi8(-1, 2, -1, -1, -1, 6, -1, -1, const __m128i perm2 = _mm_setr_epi8(-1, 2, -1, -1, -1, 6, -1, -1,

View file

@ -21,10 +21,15 @@
#define IsFlat IsFlat_NEON #define IsFlat IsFlat_NEON
static uint32x2_t horizontal_add_uint32x4(const uint32x4_t a) { static uint32_t horizontal_add_uint32x4(const uint32x4_t a) {
#if defined(__aarch64__)
return vaddvq_u32(a);
#else
const uint64x2_t b = vpaddlq_u32(a); const uint64x2_t b = vpaddlq_u32(a);
return vadd_u32(vreinterpret_u32_u64(vget_low_u64(b)), const uint32x2_t c = vadd_u32(vreinterpret_u32_u64(vget_low_u64(b)),
vreinterpret_u32_u64(vget_high_u64(b))); vreinterpret_u32_u64(vget_high_u64(b)));
return vget_lane_u32(c, 0);
#endif
} }
static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks, static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks,
@ -45,7 +50,7 @@ static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks,
levels += 16; levels += 16;
} }
return thresh >= (int32_t)vget_lane_u32(horizontal_add_uint32x4(sum), 0); return thresh >= (int)horizontal_add_uint32x4(sum);
} }
#else #else

View file

@ -85,7 +85,7 @@ static void RescalerImportRowExpand_SSE2(WebPRescaler* const wrk,
const __m128i mult = _mm_cvtsi32_si128(((x_add - accum) << 16) | accum); const __m128i mult = _mm_cvtsi32_si128(((x_add - accum) << 16) | accum);
const __m128i out = _mm_madd_epi16(cur_pixels, mult); const __m128i out = _mm_madd_epi16(cur_pixels, mult);
assert(sizeof(*frow) == sizeof(uint32_t)); assert(sizeof(*frow) == sizeof(uint32_t));
WebPUint32ToMem((uint8_t*)frow, _mm_cvtsi128_si32(out)); WebPInt32ToMem((uint8_t*)frow, _mm_cvtsi128_si32(out));
frow += 1; frow += 1;
if (frow >= frow_end) break; if (frow >= frow_end) break;
accum -= wrk->x_sub; accum -= wrk->x_sub;
@ -132,7 +132,7 @@ static void RescalerImportRowShrink_SSE2(WebPRescaler* const wrk,
__m128i base = zero; __m128i base = zero;
accum += wrk->x_add; accum += wrk->x_add;
while (accum > 0) { while (accum > 0) {
const __m128i A = _mm_cvtsi32_si128(WebPMemToUint32(src)); const __m128i A = _mm_cvtsi32_si128(WebPMemToInt32(src));
src += 4; src += 4;
base = _mm_unpacklo_epi8(A, zero); base = _mm_unpacklo_epi8(A, zero);
// To avoid overflow, we need: base * x_add / x_sub < 32768 // To avoid overflow, we need: base * x_add / x_sub < 32768
@ -198,7 +198,7 @@ static WEBP_INLINE void ProcessRow_SSE2(const __m128i* const A0,
const __m128i* const mult, const __m128i* const mult,
uint8_t* const dst) { uint8_t* const dst) {
const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER);
const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0); const __m128i mask = _mm_set_epi32(~0, 0, ~0, 0);
const __m128i B0 = _mm_mul_epu32(*A0, *mult); const __m128i B0 = _mm_mul_epu32(*A0, *mult);
const __m128i B1 = _mm_mul_epu32(*A1, *mult); const __m128i B1 = _mm_mul_epu32(*A1, *mult);
const __m128i B2 = _mm_mul_epu32(*A2, *mult); const __m128i B2 = _mm_mul_epu32(*A2, *mult);

View file

@ -121,7 +121,7 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
int uv_pos, pos; \ int uv_pos, pos; \
/* 16byte-aligned array to cache reconstructed u and v */ \ /* 16byte-aligned array to cache reconstructed u and v */ \
uint8_t uv_buf[14 * 32 + 15] = { 0 }; \ uint8_t uv_buf[14 * 32 + 15] = { 0 }; \
uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \ uint8_t* const r_u = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~(uintptr_t)15); \
uint8_t* const r_v = r_u + 32; \ uint8_t* const r_v = r_u + 32; \
\ \
assert(top_y != NULL); \ assert(top_y != NULL); \

View file

@ -15,10 +15,12 @@
#if defined(WEBP_USE_SSE2) #if defined(WEBP_USE_SSE2)
#include "src/dsp/common_sse2.h"
#include <stdlib.h> #include <stdlib.h>
#include <emmintrin.h> #include <emmintrin.h>
#include "src/dsp/common_sse2.h"
#include "src/utils/utils.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Convert spans of 32 pixels to various RGB formats for the fancy upsampler. // Convert spans of 32 pixels to various RGB formats for the fancy upsampler.
@ -74,7 +76,7 @@ static WEBP_INLINE __m128i Load_HI_16_SSE2(const uint8_t* src) {
// Load and replicate the U/V samples // Load and replicate the U/V samples
static WEBP_INLINE __m128i Load_UV_HI_8_SSE2(const uint8_t* src) { static WEBP_INLINE __m128i Load_UV_HI_8_SSE2(const uint8_t* src) {
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
const __m128i tmp0 = _mm_cvtsi32_si128(*(const uint32_t*)src); const __m128i tmp0 = _mm_cvtsi32_si128(WebPMemToInt32(src));
const __m128i tmp1 = _mm_unpacklo_epi8(zero, tmp0); const __m128i tmp1 = _mm_unpacklo_epi8(zero, tmp0);
return _mm_unpacklo_epi16(tmp1, tmp1); // replicate samples return _mm_unpacklo_epi16(tmp1, tmp1); // replicate samples
} }
@ -130,7 +132,7 @@ static WEBP_INLINE void PackAndStore4444_SSE2(const __m128i* const R,
const __m128i rg0 = _mm_packus_epi16(*B, *A); const __m128i rg0 = _mm_packus_epi16(*B, *A);
const __m128i ba0 = _mm_packus_epi16(*R, *G); const __m128i ba0 = _mm_packus_epi16(*R, *G);
#endif #endif
const __m128i mask_0xf0 = _mm_set1_epi8(0xf0); const __m128i mask_0xf0 = _mm_set1_epi8((char)0xf0);
const __m128i rb1 = _mm_unpacklo_epi8(rg0, ba0); // rbrbrbrbrb... const __m128i rb1 = _mm_unpacklo_epi8(rg0, ba0); // rbrbrbrbrb...
const __m128i ga1 = _mm_unpackhi_epi8(rg0, ba0); // gagagagaga... const __m128i ga1 = _mm_unpackhi_epi8(rg0, ba0); // gagagagaga...
const __m128i rb2 = _mm_and_si128(rb1, mask_0xf0); const __m128i rb2 = _mm_and_si128(rb1, mask_0xf0);
@ -147,9 +149,10 @@ static WEBP_INLINE void PackAndStore565_SSE2(const __m128i* const R,
const __m128i r0 = _mm_packus_epi16(*R, *R); const __m128i r0 = _mm_packus_epi16(*R, *R);
const __m128i g0 = _mm_packus_epi16(*G, *G); const __m128i g0 = _mm_packus_epi16(*G, *G);
const __m128i b0 = _mm_packus_epi16(*B, *B); const __m128i b0 = _mm_packus_epi16(*B, *B);
const __m128i r1 = _mm_and_si128(r0, _mm_set1_epi8(0xf8)); const __m128i r1 = _mm_and_si128(r0, _mm_set1_epi8((char)0xf8));
const __m128i b1 = _mm_and_si128(_mm_srli_epi16(b0, 3), _mm_set1_epi8(0x1f)); const __m128i b1 = _mm_and_si128(_mm_srli_epi16(b0, 3), _mm_set1_epi8(0x1f));
const __m128i g1 = _mm_srli_epi16(_mm_and_si128(g0, _mm_set1_epi8(0xe0)), 5); const __m128i g1 =
_mm_srli_epi16(_mm_and_si128(g0, _mm_set1_epi8((char)0xe0)), 5);
const __m128i g2 = _mm_slli_epi16(_mm_and_si128(g0, _mm_set1_epi8(0x1c)), 3); const __m128i g2 = _mm_slli_epi16(_mm_and_si128(g0, _mm_set1_epi8(0x1c)), 3);
const __m128i rg = _mm_or_si128(r1, g1); const __m128i rg = _mm_or_si128(r1, g1);
const __m128i gb = _mm_or_si128(g2, b1); const __m128i gb = _mm_or_si128(g2, b1);

View file

@ -15,10 +15,12 @@
#if defined(WEBP_USE_SSE41) #if defined(WEBP_USE_SSE41)
#include "src/dsp/common_sse41.h"
#include <stdlib.h> #include <stdlib.h>
#include <smmintrin.h> #include <smmintrin.h>
#include "src/dsp/common_sse41.h"
#include "src/utils/utils.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Convert spans of 32 pixels to various RGB formats for the fancy upsampler. // Convert spans of 32 pixels to various RGB formats for the fancy upsampler.
@ -74,7 +76,7 @@ static WEBP_INLINE __m128i Load_HI_16_SSE41(const uint8_t* src) {
// Load and replicate the U/V samples // Load and replicate the U/V samples
static WEBP_INLINE __m128i Load_UV_HI_8_SSE41(const uint8_t* src) { static WEBP_INLINE __m128i Load_UV_HI_8_SSE41(const uint8_t* src) {
const __m128i zero = _mm_setzero_si128(); const __m128i zero = _mm_setzero_si128();
const __m128i tmp0 = _mm_cvtsi32_si128(*(const uint32_t*)src); const __m128i tmp0 = _mm_cvtsi32_si128(WebPMemToInt32(src));
const __m128i tmp1 = _mm_unpacklo_epi8(zero, tmp0); const __m128i tmp1 = _mm_unpacklo_epi8(zero, tmp0);
return _mm_unpacklo_epi16(tmp1, tmp1); // replicate samples return _mm_unpacklo_epi16(tmp1, tmp1); // replicate samples
} }

View file

@ -391,12 +391,14 @@ static int DoSegmentsJob(void* arg1, void* arg2) {
return ok; return ok;
} }
#ifdef WEBP_USE_THREAD
static void MergeJobs(const SegmentJob* const src, SegmentJob* const dst) { static void MergeJobs(const SegmentJob* const src, SegmentJob* const dst) {
int i; int i;
for (i = 0; i <= MAX_ALPHA; ++i) dst->alphas[i] += src->alphas[i]; for (i = 0; i <= MAX_ALPHA; ++i) dst->alphas[i] += src->alphas[i];
dst->alpha += src->alpha; dst->alpha += src->alpha;
dst->uv_alpha += src->uv_alpha; dst->uv_alpha += src->uv_alpha;
} }
#endif
// initialize the job struct with some tasks to perform // initialize the job struct with some tasks to perform
static void InitSegmentJob(VP8Encoder* const enc, SegmentJob* const job, static void InitSegmentJob(VP8Encoder* const enc, SegmentJob* const job,
@ -425,10 +427,10 @@ int VP8EncAnalyze(VP8Encoder* const enc) {
(enc->method_ <= 1); // for method 0 - 1, we need preds_[] to be filled. (enc->method_ <= 1); // for method 0 - 1, we need preds_[] to be filled.
if (do_segments) { if (do_segments) {
const int last_row = enc->mb_h_; const int last_row = enc->mb_h_;
// We give a little more than a half work to the main thread.
const int split_row = (9 * last_row + 15) >> 4;
const int total_mb = last_row * enc->mb_w_; const int total_mb = last_row * enc->mb_w_;
#ifdef WEBP_USE_THREAD #ifdef WEBP_USE_THREAD
// We give a little more than a half work to the main thread.
const int split_row = (9 * last_row + 15) >> 4;
const int kMinSplitRow = 2; // minimal rows needed for mt to be worth it const int kMinSplitRow = 2; // minimal rows needed for mt to be worth it
const int do_mt = (enc->thread_level_ > 0) && (split_row >= kMinSplitRow); const int do_mt = (enc->thread_level_ > 0) && (split_row >= kMinSplitRow);
#else #else
@ -438,6 +440,7 @@ int VP8EncAnalyze(VP8Encoder* const enc) {
WebPGetWorkerInterface(); WebPGetWorkerInterface();
SegmentJob main_job; SegmentJob main_job;
if (do_mt) { if (do_mt) {
#ifdef WEBP_USE_THREAD
SegmentJob side_job; SegmentJob side_job;
// Note the use of '&' instead of '&&' because we must call the functions // Note the use of '&' instead of '&&' because we must call the functions
// no matter what. // no matter what.
@ -455,6 +458,7 @@ int VP8EncAnalyze(VP8Encoder* const enc) {
} }
worker_interface->End(&side_job.worker); worker_interface->End(&side_job.worker);
if (ok) MergeJobs(&side_job, &main_job); // merge results together if (ok) MergeJobs(&side_job, &main_job); // merge results together
#endif // WEBP_USE_THREAD
} else { } else {
// Even for single-thread case, we use the generic Worker tools. // Even for single-thread case, we use the generic Worker tools.
InitSegmentJob(enc, &main_job, 0, last_row); InitSegmentJob(enc, &main_job, 0, last_row);

View file

@ -69,10 +69,12 @@ static int CheckNonOpaque(const uint8_t* alpha, int width, int height,
int WebPPictureHasTransparency(const WebPPicture* picture) { int WebPPictureHasTransparency(const WebPPicture* picture) {
if (picture == NULL) return 0; if (picture == NULL) return 0;
if (picture->use_argb) { if (picture->use_argb) {
const int alpha_offset = ALPHA_OFFSET; if (picture->argb != NULL) {
return CheckNonOpaque((const uint8_t*)picture->argb + alpha_offset, return CheckNonOpaque((const uint8_t*)picture->argb + ALPHA_OFFSET,
picture->width, picture->height, picture->width, picture->height,
4, picture->argb_stride * sizeof(*picture->argb)); 4, picture->argb_stride * sizeof(*picture->argb));
}
return 0;
} }
return CheckNonOpaque(picture->a, picture->width, picture->height, return CheckNonOpaque(picture->a, picture->width, picture->height,
1, picture->a_stride); 1, picture->a_stride);
@ -170,21 +172,6 @@ static const int kMinDimensionIterativeConversion = 4;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Main function // Main function
extern void SharpYuvInit(VP8CPUInfo cpu_info_func);
static void SafeInitSharpYuv(void) {
#if defined(WEBP_USE_THREAD) && !defined(_WIN32)
static pthread_mutex_t initsharpyuv_lock = PTHREAD_MUTEX_INITIALIZER;
if (pthread_mutex_lock(&initsharpyuv_lock)) return;
#endif
SharpYuvInit(VP8GetCPUInfo);
#if defined(WEBP_USE_THREAD) && !defined(_WIN32)
(void)pthread_mutex_unlock(&initsharpyuv_lock);
#endif
}
static int PreprocessARGB(const uint8_t* r_ptr, static int PreprocessARGB(const uint8_t* r_ptr,
const uint8_t* g_ptr, const uint8_t* g_ptr,
const uint8_t* b_ptr, const uint8_t* b_ptr,
@ -481,6 +468,8 @@ static WEBP_INLINE void ConvertRowsToUV(const uint16_t* rgb,
} }
} }
extern void SharpYuvInit(VP8CPUInfo cpu_info_func);
static int ImportYUVAFromRGBA(const uint8_t* r_ptr, static int ImportYUVAFromRGBA(const uint8_t* r_ptr,
const uint8_t* g_ptr, const uint8_t* g_ptr,
const uint8_t* b_ptr, const uint8_t* b_ptr,
@ -516,7 +505,7 @@ static int ImportYUVAFromRGBA(const uint8_t* r_ptr,
} }
if (use_iterative_conversion) { if (use_iterative_conversion) {
SafeInitSharpYuv(); SharpYuvInit(VP8GetCPUInfo);
if (!PreprocessARGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, picture)) { if (!PreprocessARGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, picture)) {
return 0; return 0;
} }

View file

@ -31,8 +31,8 @@ extern "C" {
// version numbers // version numbers
#define ENC_MAJ_VERSION 1 #define ENC_MAJ_VERSION 1
#define ENC_MIN_VERSION 2 #define ENC_MIN_VERSION 3
#define ENC_REV_VERSION 4 #define ENC_REV_VERSION 0
enum { MAX_LF_LEVELS = 64, // Maximum loop filter level enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost

View file

@ -361,10 +361,11 @@ typedef enum {
kHistoTotal // Must be last. kHistoTotal // Must be last.
} HistoIx; } HistoIx;
static void AddSingleSubGreen(int p, uint32_t* const r, uint32_t* const b) { static void AddSingleSubGreen(uint32_t p,
const int green = p >> 8; // The upper bits are masked away later. uint32_t* const r, uint32_t* const b) {
++r[((p >> 16) - green) & 0xff]; const int green = (int)p >> 8; // The upper bits are masked away later.
++b[((p >> 0) - green) & 0xff]; ++r[(((int)p >> 16) - green) & 0xff];
++b[(((int)p >> 0) - green) & 0xff];
} }
static void AddSingle(uint32_t p, static void AddSingle(uint32_t p,
@ -1354,7 +1355,7 @@ static int EncodeImageInternal(
static void ApplySubtractGreen(VP8LEncoder* const enc, int width, int height, static void ApplySubtractGreen(VP8LEncoder* const enc, int width, int height,
VP8LBitWriter* const bw) { VP8LBitWriter* const bw) {
VP8LPutBits(bw, TRANSFORM_PRESENT, 1); VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
VP8LPutBits(bw, SUBTRACT_GREEN, 2); VP8LPutBits(bw, SUBTRACT_GREEN_TRANSFORM, 2);
VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height); VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height);
} }

View file

@ -28,8 +28,8 @@ extern "C" {
// Defines and constants. // Defines and constants.
#define MUX_MAJ_VERSION 1 #define MUX_MAJ_VERSION 1
#define MUX_MIN_VERSION 2 #define MUX_MIN_VERSION 3
#define MUX_REV_VERSION 4 #define MUX_REV_VERSION 0
// Chunk object. // Chunk object.
typedef struct WebPChunk WebPChunk; typedef struct WebPChunk WebPChunk;

View file

@ -148,9 +148,9 @@ int VP8GetSigned(VP8BitReader* WEBP_RESTRICT const br, int v,
const range_t value = (range_t)(br->value_ >> pos); const range_t value = (range_t)(br->value_ >> pos);
const int32_t mask = (int32_t)(split - value) >> 31; // -1 or 0 const int32_t mask = (int32_t)(split - value) >> 31; // -1 or 0
br->bits_ -= 1; br->bits_ -= 1;
br->range_ += mask; br->range_ += (range_t)mask;
br->range_ |= 1; br->range_ |= 1;
br->value_ -= (bit_t)((split + 1) & mask) << pos; br->value_ -= (bit_t)((split + 1) & (uint32_t)mask) << pos;
BT_TRACK(br); BT_TRACK(br);
return (v ^ mask) - mask; return (v ^ mask) - mask;
} }

View file

@ -142,7 +142,7 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
{ {
int step; // step size to replicate values in current table int step; // step size to replicate values in current table
uint32_t low = -1; // low bits for current root entry uint32_t low = 0xffffffffu; // low bits for current root entry
uint32_t mask = total_size - 1; // mask for low bits uint32_t mask = total_size - 1; // mask for low bits
uint32_t key = 0; // reversed prefix code uint32_t key = 0; // reversed prefix code
int num_nodes = 1; // number of Huffman tree nodes int num_nodes = 1; // number of Huffman tree nodes

View file

@ -64,7 +64,8 @@ WEBP_EXTERN void WebPSafeFree(void* const ptr);
// Alignment // Alignment
#define WEBP_ALIGN_CST 31 #define WEBP_ALIGN_CST 31
#define WEBP_ALIGN(PTR) (((uintptr_t)(PTR) + WEBP_ALIGN_CST) & ~WEBP_ALIGN_CST) #define WEBP_ALIGN(PTR) (((uintptr_t)(PTR) + WEBP_ALIGN_CST) & \
~(uintptr_t)WEBP_ALIGN_CST)
#include <string.h> #include <string.h>
// memcpy() is the safe way of moving potentially unaligned 32b memory. // memcpy() is the safe way of moving potentially unaligned 32b memory.
@ -73,10 +74,19 @@ static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) {
memcpy(&A, ptr, sizeof(A)); memcpy(&A, ptr, sizeof(A));
return A; return A;
} }
static WEBP_INLINE int32_t WebPMemToInt32(const uint8_t* const ptr) {
return (int32_t)WebPMemToUint32(ptr);
}
static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) {
memcpy(ptr, &val, sizeof(val)); memcpy(ptr, &val, sizeof(val));
} }
static WEBP_INLINE void WebPInt32ToMem(uint8_t* const ptr, int val) {
WebPUint32ToMem(ptr, (uint32_t)val);
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Reading/writing data. // Reading/writing data.

View file

@ -55,7 +55,7 @@
typedef enum { typedef enum {
PREDICTOR_TRANSFORM = 0, PREDICTOR_TRANSFORM = 0,
CROSS_COLOR_TRANSFORM = 1, CROSS_COLOR_TRANSFORM = 1,
SUBTRACT_GREEN = 2, SUBTRACT_GREEN_TRANSFORM = 2,
COLOR_INDEXING_TRANSFORM = 3 COLOR_INDEXING_TRANSFORM = 3
} VP8LImageTransformType; } VP8LImageTransformType;

View file

@ -42,7 +42,11 @@ typedef long long int int64_t;
# if defined(__GNUC__) && __GNUC__ >= 4 # if defined(__GNUC__) && __GNUC__ >= 4
# define WEBP_EXTERN extern __attribute__ ((visibility ("default"))) # define WEBP_EXTERN extern __attribute__ ((visibility ("default")))
# else # else
# define WEBP_EXTERN extern # if defined(_MSC_VER) && defined(WEBP_DLL)
# define WEBP_EXTERN __declspec(dllexport)
# else
# define WEBP_EXTERN extern
# endif
# endif /* __GNUC__ >= 4 */ # endif /* __GNUC__ >= 4 */
#endif /* WEBP_EXTERN */ #endif /* WEBP_EXTERN */