libwebp: Sync with upstream 1.3.0
(cherry picked from commit d8e8517d11
)
This commit is contained in:
parent
807e9038d2
commit
a9d19a97ec
|
@ -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",
|
||||||
|
|
|
@ -265,7 +265,7 @@ from the Android NDK r18.
|
||||||
## 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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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"
|
|
@ -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_
|
|
@ -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); }
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,8 @@ 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(
|
||||||
|
const SharpYuvColorSpace* yuv_color_space,
|
||||||
SharpYuvConversionMatrix* matrix);
|
SharpYuvConversionMatrix* matrix);
|
||||||
|
|
||||||
// Enums for precomputed conversion matrices.
|
// Enums for precomputed conversion matrices.
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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_
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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" {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ 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) {
|
||||||
|
@ -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);
|
||||||
|
|
|
@ -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]);
|
||||||
|
@ -290,7 +286,7 @@ GENERATE_PREDICTOR_2(9, upper[i + 1])
|
||||||
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]);
|
||||||
|
@ -388,7 +384,7 @@ static void PredictorAdd11_SSE2(const uint32_t* in, const uint32_t* upper,
|
||||||
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)
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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); \
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -69,11 +69,13 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
# if defined(_MSC_VER) && defined(WEBP_DLL)
|
||||||
|
# define WEBP_EXTERN __declspec(dllexport)
|
||||||
|
# else
|
||||||
# define WEBP_EXTERN extern
|
# define WEBP_EXTERN extern
|
||||||
|
# endif
|
||||||
# endif /* __GNUC__ >= 4 */
|
# endif /* __GNUC__ >= 4 */
|
||||||
#endif /* WEBP_EXTERN */
|
#endif /* WEBP_EXTERN */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue