Path: blob/master/3rdparty/libwebp/src/dsp/lossless_enc_mips_dsp_r2.c
16348 views
// Copyright 2015 Google Inc. All Rights Reserved.1//2// Use of this source code is governed by a BSD-style license3// that can be found in the COPYING file in the root of the source4// tree. An additional intellectual property rights grant can be found5// in the file PATENTS. All contributing project authors may6// be found in the AUTHORS file in the root of the source tree.7// -----------------------------------------------------------------------------8//9// Image transform methods for lossless encoder.10//11// Author(s): Djordje Pesut ([email protected])12// Jovan Zelincevic ([email protected])1314#include "src/dsp/dsp.h"1516#if defined(WEBP_USE_MIPS_DSP_R2)1718#include "src/dsp/lossless.h"1920static void SubtractGreenFromBlueAndRed_MIPSdspR2(uint32_t* argb_data,21int num_pixels) {22uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;23uint32_t* const p_loop1_end = argb_data + (num_pixels & ~3);24uint32_t* const p_loop2_end = p_loop1_end + (num_pixels & 3);25__asm__ volatile (26".set push \n\t"27".set noreorder \n\t"28"beq %[argb_data], %[p_loop1_end], 3f \n\t"29" nop \n\t"30"0: \n\t"31"lw %[temp0], 0(%[argb_data]) \n\t"32"lw %[temp1], 4(%[argb_data]) \n\t"33"lw %[temp2], 8(%[argb_data]) \n\t"34"lw %[temp3], 12(%[argb_data]) \n\t"35"ext %[temp4], %[temp0], 8, 8 \n\t"36"ext %[temp5], %[temp1], 8, 8 \n\t"37"ext %[temp6], %[temp2], 8, 8 \n\t"38"ext %[temp7], %[temp3], 8, 8 \n\t"39"addiu %[argb_data], %[argb_data], 16 \n\t"40"replv.ph %[temp4], %[temp4] \n\t"41"replv.ph %[temp5], %[temp5] \n\t"42"replv.ph %[temp6], %[temp6] \n\t"43"replv.ph %[temp7], %[temp7] \n\t"44"subu.qb %[temp0], %[temp0], %[temp4] \n\t"45"subu.qb %[temp1], %[temp1], %[temp5] \n\t"46"subu.qb %[temp2], %[temp2], %[temp6] \n\t"47"subu.qb %[temp3], %[temp3], %[temp7] \n\t"48"sw %[temp0], -16(%[argb_data]) \n\t"49"sw %[temp1], -12(%[argb_data]) \n\t"50"sw %[temp2], -8(%[argb_data]) \n\t"51"bne %[argb_data], %[p_loop1_end], 0b \n\t"52" sw %[temp3], -4(%[argb_data]) \n\t"53"3: \n\t"54"beq %[argb_data], %[p_loop2_end], 2f \n\t"55" nop \n\t"56"1: \n\t"57"lw %[temp0], 0(%[argb_data]) \n\t"58"addiu %[argb_data], %[argb_data], 4 \n\t"59"ext %[temp4], %[temp0], 8, 8 \n\t"60"replv.ph %[temp4], %[temp4] \n\t"61"subu.qb %[temp0], %[temp0], %[temp4] \n\t"62"bne %[argb_data], %[p_loop2_end], 1b \n\t"63" sw %[temp0], -4(%[argb_data]) \n\t"64"2: \n\t"65".set pop \n\t"66: [argb_data]"+&r"(argb_data), [temp0]"=&r"(temp0),67[temp1]"=&r"(temp1), [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),68[temp4]"=&r"(temp4), [temp5]"=&r"(temp5), [temp6]"=&r"(temp6),69[temp7]"=&r"(temp7)70: [p_loop1_end]"r"(p_loop1_end), [p_loop2_end]"r"(p_loop2_end)71: "memory"72);73}7475static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred,76int8_t color) {77return (uint32_t)((int)(color_pred) * color) >> 5;78}7980static void TransformColor_MIPSdspR2(const VP8LMultipliers* const m,81uint32_t* data, int num_pixels) {82int temp0, temp1, temp2, temp3, temp4, temp5;83uint32_t argb, argb1, new_red, new_red1;84const uint32_t G_to_R = m->green_to_red_;85const uint32_t G_to_B = m->green_to_blue_;86const uint32_t R_to_B = m->red_to_blue_;87uint32_t* const p_loop_end = data + (num_pixels & ~1);88__asm__ volatile (89".set push \n\t"90".set noreorder \n\t"91"beq %[data], %[p_loop_end], 1f \n\t"92" nop \n\t"93"replv.ph %[temp0], %[G_to_R] \n\t"94"replv.ph %[temp1], %[G_to_B] \n\t"95"replv.ph %[temp2], %[R_to_B] \n\t"96"shll.ph %[temp0], %[temp0], 8 \n\t"97"shll.ph %[temp1], %[temp1], 8 \n\t"98"shll.ph %[temp2], %[temp2], 8 \n\t"99"shra.ph %[temp0], %[temp0], 8 \n\t"100"shra.ph %[temp1], %[temp1], 8 \n\t"101"shra.ph %[temp2], %[temp2], 8 \n\t"102"0: \n\t"103"lw %[argb], 0(%[data]) \n\t"104"lw %[argb1], 4(%[data]) \n\t"105"lhu %[new_red], 2(%[data]) \n\t"106"lhu %[new_red1], 6(%[data]) \n\t"107"precrq.qb.ph %[temp3], %[argb], %[argb1] \n\t"108"precr.qb.ph %[temp4], %[argb], %[argb1] \n\t"109"preceu.ph.qbra %[temp3], %[temp3] \n\t"110"preceu.ph.qbla %[temp4], %[temp4] \n\t"111"shll.ph %[temp3], %[temp3], 8 \n\t"112"shll.ph %[temp4], %[temp4], 8 \n\t"113"shra.ph %[temp3], %[temp3], 8 \n\t"114"shra.ph %[temp4], %[temp4], 8 \n\t"115"mul.ph %[temp5], %[temp3], %[temp0] \n\t"116"mul.ph %[temp3], %[temp3], %[temp1] \n\t"117"mul.ph %[temp4], %[temp4], %[temp2] \n\t"118"addiu %[data], %[data], 8 \n\t"119"ins %[new_red1], %[new_red], 16, 16 \n\t"120"ins %[argb1], %[argb], 16, 16 \n\t"121"shra.ph %[temp5], %[temp5], 5 \n\t"122"shra.ph %[temp3], %[temp3], 5 \n\t"123"shra.ph %[temp4], %[temp4], 5 \n\t"124"subu.ph %[new_red1], %[new_red1], %[temp5] \n\t"125"subu.ph %[argb1], %[argb1], %[temp3] \n\t"126"preceu.ph.qbra %[temp5], %[new_red1] \n\t"127"subu.ph %[argb1], %[argb1], %[temp4] \n\t"128"preceu.ph.qbra %[temp3], %[argb1] \n\t"129"sb %[temp5], -2(%[data]) \n\t"130"sb %[temp3], -4(%[data]) \n\t"131"sra %[temp5], %[temp5], 16 \n\t"132"sra %[temp3], %[temp3], 16 \n\t"133"sb %[temp5], -6(%[data]) \n\t"134"bne %[data], %[p_loop_end], 0b \n\t"135" sb %[temp3], -8(%[data]) \n\t"136"1: \n\t"137".set pop \n\t"138: [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),139[temp3]"=&r"(temp3), [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),140[new_red1]"=&r"(new_red1), [new_red]"=&r"(new_red),141[argb]"=&r"(argb), [argb1]"=&r"(argb1), [data]"+&r"(data)142: [G_to_R]"r"(G_to_R), [R_to_B]"r"(R_to_B),143[G_to_B]"r"(G_to_B), [p_loop_end]"r"(p_loop_end)144: "memory", "hi", "lo"145);146147if (num_pixels & 1) {148const uint32_t argb_ = data[0];149const uint32_t green = argb_ >> 8;150const uint32_t red = argb_ >> 16;151uint32_t new_blue = argb_;152new_red = red;153new_red -= ColorTransformDelta(m->green_to_red_, green);154new_red &= 0xff;155new_blue -= ColorTransformDelta(m->green_to_blue_, green);156new_blue -= ColorTransformDelta(m->red_to_blue_, red);157new_blue &= 0xff;158data[0] = (argb_ & 0xff00ff00u) | (new_red << 16) | (new_blue);159}160}161162static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue,163uint8_t red_to_blue,164uint32_t argb) {165const uint32_t green = argb >> 8;166const uint32_t red = argb >> 16;167uint8_t new_blue = argb;168new_blue -= ColorTransformDelta(green_to_blue, green);169new_blue -= ColorTransformDelta(red_to_blue, red);170return (new_blue & 0xff);171}172173static void CollectColorBlueTransforms_MIPSdspR2(const uint32_t* argb,174int stride,175int tile_width,176int tile_height,177int green_to_blue,178int red_to_blue,179int histo[]) {180const int rtb = (red_to_blue << 16) | (red_to_blue & 0xffff);181const int gtb = (green_to_blue << 16) | (green_to_blue & 0xffff);182const uint32_t mask = 0xff00ffu;183while (tile_height-- > 0) {184int x;185const uint32_t* p_argb = argb;186argb += stride;187for (x = 0; x < (tile_width >> 1); ++x) {188int temp0, temp1, temp2, temp3, temp4, temp5, temp6;189__asm__ volatile (190"lw %[temp0], 0(%[p_argb]) \n\t"191"lw %[temp1], 4(%[p_argb]) \n\t"192"precr.qb.ph %[temp2], %[temp0], %[temp1] \n\t"193"ins %[temp1], %[temp0], 16, 16 \n\t"194"shra.ph %[temp2], %[temp2], 8 \n\t"195"shra.ph %[temp3], %[temp1], 8 \n\t"196"mul.ph %[temp5], %[temp2], %[rtb] \n\t"197"mul.ph %[temp6], %[temp3], %[gtb] \n\t"198"and %[temp4], %[temp1], %[mask] \n\t"199"addiu %[p_argb], %[p_argb], 8 \n\t"200"shra.ph %[temp5], %[temp5], 5 \n\t"201"shra.ph %[temp6], %[temp6], 5 \n\t"202"subu.qb %[temp2], %[temp4], %[temp5] \n\t"203"subu.qb %[temp2], %[temp2], %[temp6] \n\t"204: [p_argb]"+&r"(p_argb), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),205[temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4),206[temp5]"=&r"(temp5), [temp6]"=&r"(temp6)207: [rtb]"r"(rtb), [gtb]"r"(gtb), [mask]"r"(mask)208: "memory", "hi", "lo"209);210++histo[(uint8_t)(temp2 >> 16)];211++histo[(uint8_t)temp2];212}213if (tile_width & 1) {214++histo[TransformColorBlue(green_to_blue, red_to_blue, *p_argb)];215}216}217}218219static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red,220uint32_t argb) {221const uint32_t green = argb >> 8;222uint32_t new_red = argb >> 16;223new_red -= ColorTransformDelta(green_to_red, green);224return (new_red & 0xff);225}226227static void CollectColorRedTransforms_MIPSdspR2(const uint32_t* argb,228int stride,229int tile_width,230int tile_height,231int green_to_red,232int histo[]) {233const int gtr = (green_to_red << 16) | (green_to_red & 0xffff);234while (tile_height-- > 0) {235int x;236const uint32_t* p_argb = argb;237argb += stride;238for (x = 0; x < (tile_width >> 1); ++x) {239int temp0, temp1, temp2, temp3, temp4;240__asm__ volatile (241"lw %[temp0], 0(%[p_argb]) \n\t"242"lw %[temp1], 4(%[p_argb]) \n\t"243"precrq.ph.w %[temp4], %[temp0], %[temp1] \n\t"244"ins %[temp1], %[temp0], 16, 16 \n\t"245"shra.ph %[temp3], %[temp1], 8 \n\t"246"mul.ph %[temp2], %[temp3], %[gtr] \n\t"247"addiu %[p_argb], %[p_argb], 8 \n\t"248"shra.ph %[temp2], %[temp2], 5 \n\t"249"subu.qb %[temp2], %[temp4], %[temp2] \n\t"250: [p_argb]"+&r"(p_argb), [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),251[temp2]"=&r"(temp2), [temp3]"=&r"(temp3), [temp4]"=&r"(temp4)252: [gtr]"r"(gtr)253: "memory", "hi", "lo"254);255++histo[(uint8_t)(temp2 >> 16)];256++histo[(uint8_t)temp2];257}258if (tile_width & 1) {259++histo[TransformColorRed(green_to_red, *p_argb)];260}261}262}263264//------------------------------------------------------------------------------265// Entry point266267extern void VP8LEncDspInitMIPSdspR2(void);268269WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPSdspR2(void) {270VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_MIPSdspR2;271VP8LTransformColor = TransformColor_MIPSdspR2;272VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_MIPSdspR2;273VP8LCollectColorRedTransforms = CollectColorRedTransforms_MIPSdspR2;274}275276#else // !WEBP_USE_MIPS_DSP_R2277278WEBP_DSP_INIT_STUB(VP8LEncDspInitMIPSdspR2)279280#endif // WEBP_USE_MIPS_DSP_R2281282283