Index: third_party/libwebp/dsp/filters_mips_dsp_r2.c |
diff --git a/third_party/libwebp/dsp/filters_mips_dsp_r2.c b/third_party/libwebp/dsp/filters_mips_dsp_r2.c |
index 8134af511be456c1dcdd692c084703f8e8153b22..1d82e3c2e19fa02304cb88572c37064161142f78 100644 |
--- a/third_party/libwebp/dsp/filters_mips_dsp_r2.c |
+++ b/third_party/libwebp/dsp/filters_mips_dsp_r2.c |
@@ -33,10 +33,6 @@ |
assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ |
(void)height; // Silence unused warning. |
-// if INVERSE |
-// preds == &dst[-1] == &src[-1] |
-// else |
-// preds == &src[-1] != &dst[-1] |
#define DO_PREDICT_LINE(SRC, DST, LENGTH, INVERSE) do { \ |
const uint8_t* psrc = (uint8_t*)(SRC); \ |
uint8_t* pdst = (uint8_t*)(DST); \ |
@@ -45,27 +41,28 @@ |
__asm__ volatile ( \ |
".set push \n\t" \ |
".set noreorder \n\t" \ |
- "srl %[temp0], %[length], 0x2 \n\t" \ |
+ "srl %[temp0], %[length], 2 \n\t" \ |
"beqz %[temp0], 4f \n\t" \ |
- " andi %[temp6], %[length], 0x3 \n\t" \ |
+ " andi %[temp6], %[length], 3 \n\t" \ |
".if " #INVERSE " \n\t" \ |
- "lbu %[temp1], -1(%[src]) \n\t" \ |
"1: \n\t" \ |
+ "lbu %[temp1], -1(%[dst]) \n\t" \ |
"lbu %[temp2], 0(%[src]) \n\t" \ |
"lbu %[temp3], 1(%[src]) \n\t" \ |
"lbu %[temp4], 2(%[src]) \n\t" \ |
"lbu %[temp5], 3(%[src]) \n\t" \ |
+ "addu %[temp1], %[temp1], %[temp2] \n\t" \ |
+ "addu %[temp2], %[temp1], %[temp3] \n\t" \ |
+ "addu %[temp3], %[temp2], %[temp4] \n\t" \ |
+ "addu %[temp4], %[temp3], %[temp5] \n\t" \ |
+ "sb %[temp1], 0(%[dst]) \n\t" \ |
+ "sb %[temp2], 1(%[dst]) \n\t" \ |
+ "sb %[temp3], 2(%[dst]) \n\t" \ |
+ "sb %[temp4], 3(%[dst]) \n\t" \ |
"addiu %[src], %[src], 4 \n\t" \ |
"addiu %[temp0], %[temp0], -1 \n\t" \ |
- "addu %[temp2], %[temp2], %[temp1] \n\t" \ |
- "addu %[temp3], %[temp3], %[temp2] \n\t" \ |
- "addu %[temp4], %[temp4], %[temp3] \n\t" \ |
- "addu %[temp1], %[temp5], %[temp4] \n\t" \ |
- "sb %[temp2], -4(%[src]) \n\t" \ |
- "sb %[temp3], -3(%[src]) \n\t" \ |
- "sb %[temp4], -2(%[src]) \n\t" \ |
"bnez %[temp0], 1b \n\t" \ |
- " sb %[temp1], -1(%[src]) \n\t" \ |
+ " addiu %[dst], %[dst], 4 \n\t" \ |
".else \n\t" \ |
"1: \n\t" \ |
"ulw %[temp1], -1(%[src]) \n\t" \ |
@@ -81,16 +78,16 @@ |
"beqz %[temp6], 3f \n\t" \ |
" nop \n\t" \ |
"2: \n\t" \ |
- "lbu %[temp1], -1(%[src]) \n\t" \ |
"lbu %[temp2], 0(%[src]) \n\t" \ |
- "addiu %[src], %[src], 1 \n\t" \ |
".if " #INVERSE " \n\t" \ |
+ "lbu %[temp1], -1(%[dst]) \n\t" \ |
"addu %[temp3], %[temp1], %[temp2] \n\t" \ |
- "sb %[temp3], -1(%[src]) \n\t" \ |
".else \n\t" \ |
+ "lbu %[temp1], -1(%[src]) \n\t" \ |
"subu %[temp3], %[temp1], %[temp2] \n\t" \ |
- "sb %[temp3], 0(%[dst]) \n\t" \ |
".endif \n\t" \ |
+ "addiu %[src], %[src], 1 \n\t" \ |
+ "sb %[temp3], 0(%[dst]) \n\t" \ |
"addiu %[temp6], %[temp6], -1 \n\t" \ |
"bnez %[temp6], 2b \n\t" \ |
" addiu %[dst], %[dst], 1 \n\t" \ |
@@ -105,12 +102,8 @@ |
} while (0) |
static WEBP_INLINE void PredictLine(const uint8_t* src, uint8_t* dst, |
- int length, int inverse) { |
- if (inverse) { |
- DO_PREDICT_LINE(src, dst, length, 1); |
- } else { |
- DO_PREDICT_LINE(src, dst, length, 0); |
- } |
+ int length) { |
+ DO_PREDICT_LINE(src, dst, length, 0); |
} |
#define DO_PREDICT_LINE_VERTICAL(SRC, PRED, DST, LENGTH, INVERSE) do { \ |
@@ -172,16 +165,12 @@ static WEBP_INLINE void PredictLine(const uint8_t* src, uint8_t* dst, |
); \ |
} while (0) |
-#define PREDICT_LINE_ONE_PASS(SRC, PRED, DST, INVERSE) do { \ |
+#define PREDICT_LINE_ONE_PASS(SRC, PRED, DST) do { \ |
int temp1, temp2, temp3; \ |
__asm__ volatile ( \ |
"lbu %[temp1], 0(%[src]) \n\t" \ |
"lbu %[temp2], 0(%[pred]) \n\t" \ |
- ".if " #INVERSE " \n\t" \ |
- "addu %[temp3], %[temp1], %[temp2] \n\t" \ |
- ".else \n\t" \ |
"subu %[temp3], %[temp1], %[temp2] \n\t" \ |
- ".endif \n\t" \ |
"sb %[temp3], 0(%[dst]) \n\t" \ |
: [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3) \ |
: [pred]"r"((PRED)), [dst]"r"((DST)), [src]"r"((SRC)) \ |
@@ -192,10 +181,10 @@ static WEBP_INLINE void PredictLine(const uint8_t* src, uint8_t* dst, |
//------------------------------------------------------------------------------ |
// Horizontal filter. |
-#define FILTER_LINE_BY_LINE(INVERSE) do { \ |
+#define FILTER_LINE_BY_LINE do { \ |
while (row < last_row) { \ |
- PREDICT_LINE_ONE_PASS(in, preds - stride, out, INVERSE); \ |
- DO_PREDICT_LINE(in + 1, out + 1, width - 1, INVERSE); \ |
+ PREDICT_LINE_ONE_PASS(in, preds - stride, out); \ |
+ DO_PREDICT_LINE(in + 1, out + 1, width - 1, 0); \ |
++row; \ |
preds += stride; \ |
in += stride; \ |
@@ -206,19 +195,19 @@ static WEBP_INLINE void PredictLine(const uint8_t* src, uint8_t* dst, |
static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, |
int width, int height, int stride, |
int row, int num_rows, |
- int inverse, uint8_t* out) { |
+ uint8_t* out) { |
const uint8_t* preds; |
const size_t start_offset = row * stride; |
const int last_row = row + num_rows; |
SANITY_CHECK(in, out); |
in += start_offset; |
out += start_offset; |
- preds = inverse ? out : in; |
+ preds = in; |
if (row == 0) { |
// Leftmost pixel is the same as input for topmost scanline. |
out[0] = in[0]; |
- PredictLine(in + 1, out + 1, width - 1, inverse); |
+ PredictLine(in + 1, out + 1, width - 1); |
row = 1; |
preds += stride; |
in += stride; |
@@ -226,31 +215,21 @@ static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, |
} |
// Filter line-by-line. |
- if (inverse) { |
- FILTER_LINE_BY_LINE(1); |
- } else { |
- FILTER_LINE_BY_LINE(0); |
- } |
+ FILTER_LINE_BY_LINE; |
} |
- |
#undef FILTER_LINE_BY_LINE |
static void HorizontalFilter(const uint8_t* data, int width, int height, |
int stride, uint8_t* filtered_data) { |
- DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data); |
-} |
- |
-static void HorizontalUnfilter(int width, int height, int stride, int row, |
- int num_rows, uint8_t* data) { |
- DoHorizontalFilter(data, width, height, stride, row, num_rows, 1, data); |
+ DoHorizontalFilter(data, width, height, stride, 0, height, filtered_data); |
} |
//------------------------------------------------------------------------------ |
// Vertical filter. |
-#define FILTER_LINE_BY_LINE(INVERSE) do { \ |
+#define FILTER_LINE_BY_LINE do { \ |
while (row < last_row) { \ |
- DO_PREDICT_LINE_VERTICAL(in, preds, out, width, INVERSE); \ |
+ DO_PREDICT_LINE_VERTICAL(in, preds, out, width, 0); \ |
++row; \ |
preds += stride; \ |
in += stride; \ |
@@ -260,21 +239,20 @@ static void HorizontalUnfilter(int width, int height, int stride, int row, |
static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, |
int width, int height, int stride, |
- int row, int num_rows, |
- int inverse, uint8_t* out) { |
+ int row, int num_rows, uint8_t* out) { |
const uint8_t* preds; |
const size_t start_offset = row * stride; |
const int last_row = row + num_rows; |
SANITY_CHECK(in, out); |
in += start_offset; |
out += start_offset; |
- preds = inverse ? out : in; |
+ preds = in; |
if (row == 0) { |
// Very first top-left pixel is copied. |
out[0] = in[0]; |
// Rest of top scan-line is left-predicted. |
- PredictLine(in + 1, out + 1, width - 1, inverse); |
+ PredictLine(in + 1, out + 1, width - 1); |
row = 1; |
in += stride; |
out += stride; |
@@ -284,24 +262,13 @@ static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, |
} |
// Filter line-by-line. |
- if (inverse) { |
- FILTER_LINE_BY_LINE(1); |
- } else { |
- FILTER_LINE_BY_LINE(0); |
- } |
+ FILTER_LINE_BY_LINE; |
} |
- |
#undef FILTER_LINE_BY_LINE |
-#undef DO_PREDICT_LINE_VERTICAL |
static void VerticalFilter(const uint8_t* data, int width, int height, |
int stride, uint8_t* filtered_data) { |
- DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data); |
-} |
- |
-static void VerticalUnfilter(int width, int height, int stride, int row, |
- int num_rows, uint8_t* data) { |
- DoVerticalFilter(data, width, height, stride, row, num_rows, 1, data); |
+ DoVerticalFilter(data, width, height, stride, 0, height, filtered_data); |
} |
//------------------------------------------------------------------------------ |
@@ -321,10 +288,10 @@ static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { |
return temp0; |
} |
-#define FILTER_LINE_BY_LINE(INVERSE, PREDS, OPERATION) do { \ |
+#define FILTER_LINE_BY_LINE(PREDS, OPERATION) do { \ |
while (row < last_row) { \ |
int w; \ |
- PREDICT_LINE_ONE_PASS(in, PREDS - stride, out, INVERSE); \ |
+ PREDICT_LINE_ONE_PASS(in, PREDS - stride, out); \ |
for (w = 1; w < width; ++w) { \ |
const int pred = GradientPredictor(PREDS[w - 1], \ |
PREDS[w - stride], \ |
@@ -339,20 +306,19 @@ static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { |
static WEBP_INLINE void DoGradientFilter(const uint8_t* in, |
int width, int height, int stride, |
- int row, int num_rows, |
- int inverse, uint8_t* out) { |
+ int row, int num_rows, uint8_t* out) { |
const uint8_t* preds; |
const size_t start_offset = row * stride; |
const int last_row = row + num_rows; |
SANITY_CHECK(in, out); |
in += start_offset; |
out += start_offset; |
- preds = inverse ? out : in; |
+ preds = in; |
// left prediction for top scan-line |
if (row == 0) { |
out[0] = in[0]; |
- PredictLine(in + 1, out + 1, width - 1, inverse); |
+ PredictLine(in + 1, out + 1, width - 1); |
row = 1; |
preds += stride; |
in += stride; |
@@ -360,25 +326,49 @@ static WEBP_INLINE void DoGradientFilter(const uint8_t* in, |
} |
// Filter line-by-line. |
- if (inverse) { |
- FILTER_LINE_BY_LINE(1, out, +); |
- } else { |
- FILTER_LINE_BY_LINE(0, in, -); |
- } |
+ FILTER_LINE_BY_LINE(in, -); |
} |
- |
#undef FILTER_LINE_BY_LINE |
static void GradientFilter(const uint8_t* data, int width, int height, |
int stride, uint8_t* filtered_data) { |
- DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data); |
+ DoGradientFilter(data, width, height, stride, 0, height, filtered_data); |
} |
-static void GradientUnfilter(int width, int height, int stride, int row, |
- int num_rows, uint8_t* data) { |
- DoGradientFilter(data, width, height, stride, row, num_rows, 1, data); |
+//------------------------------------------------------------------------------ |
+ |
+static void HorizontalUnfilter(const uint8_t* prev, const uint8_t* in, |
+ uint8_t* out, int width) { |
+ out[0] = in[0] + (prev == NULL ? 0 : prev[0]); |
+ DO_PREDICT_LINE(in + 1, out + 1, width - 1, 1); |
} |
+static void VerticalUnfilter(const uint8_t* prev, const uint8_t* in, |
+ uint8_t* out, int width) { |
+ if (prev == NULL) { |
+ HorizontalUnfilter(NULL, in, out, width); |
+ } else { |
+ DO_PREDICT_LINE_VERTICAL(in, prev, out, width, 1); |
+ } |
+} |
+ |
+static void GradientUnfilter(const uint8_t* prev, const uint8_t* in, |
+ uint8_t* out, int width) { |
+ if (prev == NULL) { |
+ HorizontalUnfilter(NULL, in, out, width); |
+ } else { |
+ uint8_t top = prev[0], top_left = top, left = top; |
+ int i; |
+ for (i = 0; i < width; ++i) { |
+ top = prev[i]; // need to read this first, in case prev==dst |
+ left = in[i] + GradientPredictor(left, top, top_left); |
+ top_left = top; |
+ out[i] = left; |
+ } |
+ } |
+} |
+ |
+#undef DO_PREDICT_LINE_VERTICAL |
#undef PREDICT_LINE_ONE_PASS |
#undef DO_PREDICT_LINE |
#undef SANITY_CHECK |
@@ -389,13 +379,13 @@ static void GradientUnfilter(int width, int height, int stride, int row, |
extern void VP8FiltersInitMIPSdspR2(void); |
WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitMIPSdspR2(void) { |
- WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter; |
- WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter; |
- WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter; |
- |
WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter; |
WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter; |
WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter; |
+ |
+ WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter; |
+ WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter; |
+ WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter; |
} |
#else // !WEBP_USE_MIPS_DSP_R2 |