/* * Copyright (c) 2010 The VP8 project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE 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 "memory.h" #include "preproc.h" #include "pragmas.h" /**************************************************************************** * Macros ****************************************************************************/ #define FRAMECOUNT 7 #define ROUNDUP32(X) ( ( ( (unsigned long) X ) + 31 )&( 0xFFFFFFE0 ) ) /**************************************************************************** * Imports ****************************************************************************/ extern void vpx_get_processor_flags(int *mmx_enabled, int *xmm_enabled, int *wmt_enabled); /**************************************************************************** * Exported Global Variables ****************************************************************************/ void (*temp_filter)(pre_proc_instance *ppi, unsigned char *s, unsigned char *d, int bytes, int strength); /**************************************************************************** * * ROUTINE : temp_filter_wmt * * INPUTS : pre_proc_instance *ppi : Pointer to pre-processor instance. * unsigned char *s : Pointer to source frame. * unsigned char *d : Pointer to destination frame. * int bytes : Number of bytes to filter. * int strength : Strength of filter to apply. * * OUTPUTS : None. * * RETURNS : void * * FUNCTION : Performs a closesness adjusted temporarl blur * * SPECIAL NOTES : Destination frame can be same as source frame. * ****************************************************************************/ void temp_filter_wmt ( pre_proc_instance *ppi, unsigned char *s, unsigned char *d, int bytes, int strength ) { int byte = 0; unsigned char *frameptr = ppi->frame_buffer; __declspec(align(16)) unsigned short threes[] = { 3, 3, 3, 3, 3, 3, 3, 3}; __declspec(align(16)) unsigned short sixteens[] = {16, 16, 16, 16, 16, 16, 16, 16}; if (ppi->frame == 0) { do { int i; int frame = 0; do { for (i = 0; i < 8; i++) { *frameptr = s[byte+i]; ++frameptr; } ++frame; } while (frame < FRAMECOUNT); for (i = 0; i < 8; i++) d[byte+i] = s[byte+i]; byte += 8; } while (byte < bytes); } else { int i; int offset2 = (ppi->frame % FRAMECOUNT); do { __declspec(align(16)) unsigned short counts[8]; __declspec(align(16)) unsigned short sums[8]; __asm { mov eax, offset2 mov edi, s // source pixels pxor xmm1, xmm1 // accumulator pxor xmm7, xmm7 mov esi, frameptr // accumulator pxor xmm2, xmm2 // count movq xmm3, QWORD PTR [edi] movq QWORD PTR [esi+8*eax], xmm3 punpcklbw xmm3, xmm2 // xmm3 source pixels mov ecx, FRAMECOUNT next_frame: movq xmm4, QWORD PTR [esi] // get frame buffer values punpcklbw xmm4, xmm7 // xmm4 frame buffer pixels movdqa xmm6, xmm4 // save the pixel values psubsw xmm4, xmm3 // subtracted pixel values pmullw xmm4, xmm4 // square xmm4 movd xmm5, strength psrlw xmm4, xmm5 // should be strength pmullw xmm4, threes // 3 * modifier movdqa xmm5, sixteens // 16s psubusw xmm5, xmm4 // 16 - modifiers movdqa xmm4, xmm5 // save the modifiers pmullw xmm4, xmm6 // multiplier values paddusw xmm1, xmm4 // accumulator paddusw xmm2, xmm5 // count add esi, 8 // next frame dec ecx // next set of eight pixels jnz next_frame movdqa counts, xmm2 psrlw xmm2, 1 // divide count by 2 for rounding paddusw xmm1, xmm2 // rounding added in mov frameptr, esi movdqa sums, xmm1 } for (i = 0; i < 8; i++) { int blurvalue = sums[i] * ppi->fixed_divide[counts[i]]; blurvalue >>= 16; d[i] = blurvalue; } s += 8; d += 8; byte += 8; } while (byte < bytes); } ++ppi->frame; __asm emms } /**************************************************************************** * * ROUTINE : temp_filter_mmx * * INPUTS : pre_proc_instance *ppi : Pointer to pre-processor instance. * unsigned char *s : Pointer to source frame. * unsigned char *d : Pointer to destination frame. * int bytes : Number of bytes to filter. * int strength : Strength of filter to apply. * * OUTPUTS : None. * * RETURNS : void * * FUNCTION : Performs a closesness adjusted temporarl blur * * SPECIAL NOTES : Destination frame can be same as source frame. * ****************************************************************************/ void temp_filter_mmx ( pre_proc_instance *ppi, unsigned char *s, unsigned char *d, int bytes, int strength ) { int byte = 0; unsigned char *frameptr = ppi->frame_buffer; __declspec(align(16)) unsigned short threes[] = { 3, 3, 3, 3}; __declspec(align(16)) unsigned short sixteens[] = {16, 16, 16, 16}; if (ppi->frame == 0) { do { int i; int frame = 0; do { for (i = 0; i < 4; i++) { *frameptr = s[byte+i]; ++frameptr; } ++frame; } while (frame < FRAMECOUNT); for (i = 0; i < 4; i++) d[byte+i] = s[byte+i]; byte += 4; } while (byte < bytes); } else { int i; int offset2 = (ppi->frame % FRAMECOUNT); do { __declspec(align(16)) unsigned short counts[8]; __declspec(align(16)) unsigned short sums[8]; __asm { mov eax, offset2 mov edi, s // source pixels pxor mm1, mm1 // accumulator pxor mm7, mm7 mov esi, frameptr // accumulator pxor mm2, mm2 // count movd mm3, DWORD PTR [edi] movd DWORD PTR [esi+4*eax], mm3 punpcklbw mm3, mm2 // mm3 source pixels mov ecx, FRAMECOUNT next_frame: movd mm4, DWORD PTR [esi] // get frame buffer values punpcklbw mm4, mm7 // mm4 frame buffer pixels movq mm6, mm4 // save the pixel values psubsw mm4, mm3 // subtracted pixel values pmullw mm4, mm4 // square mm4 movd mm5, strength psrlw mm4, mm5 // should be strength pmullw mm4, threes // 3 * modifier movq mm5, sixteens // 16s psubusw mm5, mm4 // 16 - modifiers movq mm4, mm5 // save the modifiers pmullw mm4, mm6 // multiplier values paddusw mm1, mm4 // accumulator paddusw mm2, mm5 // count add esi, 4 // next frame dec ecx // next set of eight pixels jnz next_frame movq counts, mm2 psrlw mm2, 1 // divide count by 2 for rounding paddusw mm1, mm2 // rounding added in mov frameptr, esi movq sums, mm1 } for (i = 0; i < 4; i++) { int blurvalue = sums[i] * ppi->fixed_divide[counts[i]]; blurvalue >>= 16; d[i] = blurvalue; } s += 4; d += 4; byte += 4; } while (byte < bytes); } ++ppi->frame; __asm emms }