Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * RV40 decoder motion compensation functions x86-optimised
  3.  * Copyright (c) 2008 Konstantin Shishkov
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. /**
  23.  * @file
  24.  * RV40 decoder motion compensation functions x86-optimised
  25.  * 2,0 and 0,2 have h264 equivalents.
  26.  * 3,3 is bugged in the rv40 format and maps to _xy2 version
  27.  */
  28.  
  29. #include "libavcodec/rv34dsp.h"
  30. #include "libavutil/attributes.h"
  31. #include "libavutil/mem.h"
  32. #include "libavutil/x86/cpu.h"
  33. #include "dsputil_x86.h"
  34.  
  35. #if HAVE_YASM
  36. void ff_put_rv40_chroma_mc8_mmx  (uint8_t *dst, uint8_t *src,
  37.                                   int stride, int h, int x, int y);
  38. void ff_avg_rv40_chroma_mc8_mmxext(uint8_t *dst, uint8_t *src,
  39.                                    int stride, int h, int x, int y);
  40. void ff_avg_rv40_chroma_mc8_3dnow(uint8_t *dst, uint8_t *src,
  41.                                   int stride, int h, int x, int y);
  42.  
  43. void ff_put_rv40_chroma_mc4_mmx  (uint8_t *dst, uint8_t *src,
  44.                                   int stride, int h, int x, int y);
  45. void ff_avg_rv40_chroma_mc4_mmxext(uint8_t *dst, uint8_t *src,
  46.                                    int stride, int h, int x, int y);
  47. void ff_avg_rv40_chroma_mc4_3dnow(uint8_t *dst, uint8_t *src,
  48.                                   int stride, int h, int x, int y);
  49.  
  50. #define DECLARE_WEIGHT(opt) \
  51. void ff_rv40_weight_func_rnd_16_##opt(uint8_t *dst, uint8_t *src1, uint8_t *src2, \
  52.                                       int w1, int w2, ptrdiff_t stride); \
  53. void ff_rv40_weight_func_rnd_8_##opt (uint8_t *dst, uint8_t *src1, uint8_t *src2, \
  54.                                       int w1, int w2, ptrdiff_t stride); \
  55. void ff_rv40_weight_func_nornd_16_##opt(uint8_t *dst, uint8_t *src1, uint8_t *src2, \
  56.                                         int w1, int w2, ptrdiff_t stride); \
  57. void ff_rv40_weight_func_nornd_8_##opt (uint8_t *dst, uint8_t *src1, uint8_t *src2, \
  58.                                         int w1, int w2, ptrdiff_t stride);
  59. DECLARE_WEIGHT(mmxext)
  60. DECLARE_WEIGHT(sse2)
  61. DECLARE_WEIGHT(ssse3)
  62.  
  63. /** @{ */
  64. /**
  65.  * Define one qpel function.
  66.  * LOOPSIZE must be already set to the number of pixels processed per
  67.  * iteration in the inner loop of the called functions.
  68.  * COFF(x) must be already defined so as to provide the offset into any
  69.  * array of coeffs used by the called function for the qpel position x.
  70.  */
  71. #define QPEL_FUNC_DECL(OP, SIZE, PH, PV, OPT)                           \
  72. static void OP ## rv40_qpel ##SIZE ##_mc ##PH ##PV ##OPT(uint8_t *dst,  \
  73.                                                          uint8_t *src,  \
  74.                                                          ptrdiff_t stride)  \
  75. {                                                                       \
  76.     int i;                                                              \
  77.     if (PH && PV) {                                                     \
  78.         DECLARE_ALIGNED(16, uint8_t, tmp)[SIZE * (SIZE + 5)];           \
  79.         uint8_t *tmpptr = tmp + SIZE * 2;                               \
  80.         src -= stride * 2;                                              \
  81.                                                                         \
  82.         for (i = 0; i < SIZE; i += LOOPSIZE)                            \
  83.             ff_put_rv40_qpel_h ##OPT(tmp + i, SIZE, src + i, stride,    \
  84.                                      SIZE + 5, HCOFF(PH));              \
  85.         for (i = 0; i < SIZE; i += LOOPSIZE)                            \
  86.             ff_ ##OP ##rv40_qpel_v ##OPT(dst + i, stride, tmpptr + i,   \
  87.                                          SIZE, SIZE, VCOFF(PV));        \
  88.     } else if (PV) {                                                    \
  89.         for (i = 0; i < SIZE; i += LOOPSIZE)                            \
  90.             ff_ ##OP ##rv40_qpel_v ## OPT(dst + i, stride, src + i,     \
  91.                                           stride, SIZE, VCOFF(PV));     \
  92.     } else {                                                            \
  93.         for (i = 0; i < SIZE; i += LOOPSIZE)                            \
  94.             ff_ ##OP ##rv40_qpel_h ## OPT(dst + i, stride, src + i,     \
  95.                                           stride, SIZE, HCOFF(PH));     \
  96.     }                                                                   \
  97. };
  98.  
  99. /** Declare functions for sizes 8 and 16 and given operations
  100.  *  and qpel position. */
  101. #define QPEL_FUNCS_DECL(OP, PH, PV, OPT) \
  102.     QPEL_FUNC_DECL(OP,  8, PH, PV, OPT)  \
  103.     QPEL_FUNC_DECL(OP, 16, PH, PV, OPT)
  104.  
  105. /** Declare all functions for all sizes and qpel positions */
  106. #define QPEL_MC_DECL(OP, OPT)                                           \
  107. void ff_ ##OP ##rv40_qpel_h ##OPT(uint8_t *dst, ptrdiff_t dstStride,    \
  108.                                   const uint8_t *src,                   \
  109.                                   ptrdiff_t srcStride,                  \
  110.                                   int len, int m);                      \
  111. void ff_ ##OP ##rv40_qpel_v ##OPT(uint8_t *dst, ptrdiff_t dstStride,    \
  112.                                   const uint8_t *src,                   \
  113.                                   ptrdiff_t srcStride,                  \
  114.                                   int len, int m);                      \
  115. QPEL_FUNCS_DECL(OP, 0, 1, OPT)                                          \
  116. QPEL_FUNCS_DECL(OP, 0, 3, OPT)                                          \
  117. QPEL_FUNCS_DECL(OP, 1, 0, OPT)                                          \
  118. QPEL_FUNCS_DECL(OP, 1, 1, OPT)                                          \
  119. QPEL_FUNCS_DECL(OP, 1, 2, OPT)                                          \
  120. QPEL_FUNCS_DECL(OP, 1, 3, OPT)                                          \
  121. QPEL_FUNCS_DECL(OP, 2, 1, OPT)                                          \
  122. QPEL_FUNCS_DECL(OP, 2, 2, OPT)                                          \
  123. QPEL_FUNCS_DECL(OP, 2, 3, OPT)                                          \
  124. QPEL_FUNCS_DECL(OP, 3, 0, OPT)                                          \
  125. QPEL_FUNCS_DECL(OP, 3, 1, OPT)                                          \
  126. QPEL_FUNCS_DECL(OP, 3, 2, OPT)
  127. /** @} */
  128.  
  129. #define LOOPSIZE  8
  130. #define HCOFF(x)  (32 * (x - 1))
  131. #define VCOFF(x)  (32 * (x - 1))
  132. QPEL_MC_DECL(put_, _ssse3)
  133. QPEL_MC_DECL(avg_, _ssse3)
  134.  
  135. #undef LOOPSIZE
  136. #undef HCOFF
  137. #undef VCOFF
  138. #define LOOPSIZE  8
  139. #define HCOFF(x)  (64 * (x - 1))
  140. #define VCOFF(x)  (64 * (x - 1))
  141. QPEL_MC_DECL(put_, _sse2)
  142. QPEL_MC_DECL(avg_, _sse2)
  143.  
  144. #if ARCH_X86_32
  145. #undef LOOPSIZE
  146. #undef HCOFF
  147. #undef VCOFF
  148. #define LOOPSIZE  4
  149. #define HCOFF(x)  (64 * (x - 1))
  150. #define VCOFF(x)  (64 * (x - 1))
  151.  
  152. QPEL_MC_DECL(put_, _mmx)
  153.  
  154. #define ff_put_rv40_qpel_h_mmxext  ff_put_rv40_qpel_h_mmx
  155. #define ff_put_rv40_qpel_v_mmxext  ff_put_rv40_qpel_v_mmx
  156. QPEL_MC_DECL(avg_, _mmxext)
  157.  
  158. #define ff_put_rv40_qpel_h_3dnow  ff_put_rv40_qpel_h_mmx
  159. #define ff_put_rv40_qpel_v_3dnow  ff_put_rv40_qpel_v_mmx
  160. QPEL_MC_DECL(avg_, _3dnow)
  161. #endif
  162.  
  163. /** @{ */
  164. /** Set one function */
  165. #define QPEL_FUNC_SET(OP, SIZE, PH, PV, OPT)                            \
  166.     c-> OP ## pixels_tab[2 - SIZE / 8][4 * PV + PH] = OP ## rv40_qpel ##SIZE ## _mc ##PH ##PV ##OPT;
  167.  
  168. /** Set functions put and avg for sizes 8 and 16 and a given qpel position */
  169. #define QPEL_FUNCS_SET(OP, PH, PV, OPT)         \
  170.     QPEL_FUNC_SET(OP,  8, PH, PV, OPT)          \
  171.     QPEL_FUNC_SET(OP, 16, PH, PV, OPT)
  172.  
  173. /** Set all functions for all sizes and qpel positions */
  174. #define QPEL_MC_SET(OP, OPT)   \
  175. QPEL_FUNCS_SET (OP, 0, 1, OPT) \
  176. QPEL_FUNCS_SET (OP, 0, 3, OPT) \
  177. QPEL_FUNCS_SET (OP, 1, 0, OPT) \
  178. QPEL_FUNCS_SET (OP, 1, 1, OPT) \
  179. QPEL_FUNCS_SET (OP, 1, 2, OPT) \
  180. QPEL_FUNCS_SET (OP, 1, 3, OPT) \
  181. QPEL_FUNCS_SET (OP, 2, 1, OPT) \
  182. QPEL_FUNCS_SET (OP, 2, 2, OPT) \
  183. QPEL_FUNCS_SET (OP, 2, 3, OPT) \
  184. QPEL_FUNCS_SET (OP, 3, 0, OPT) \
  185. QPEL_FUNCS_SET (OP, 3, 1, OPT) \
  186. QPEL_FUNCS_SET (OP, 3, 2, OPT)
  187. /** @} */
  188.  
  189. #endif /* HAVE_YASM */
  190.  
  191. #if HAVE_MMX_INLINE
  192. static void put_rv40_qpel8_mc33_mmx(uint8_t *dst, uint8_t *src,
  193.                                     ptrdiff_t stride)
  194. {
  195.     ff_put_pixels8_xy2_mmx(dst, src, stride, 8);
  196. }
  197. static void put_rv40_qpel16_mc33_mmx(uint8_t *dst, uint8_t *src,
  198.                                      ptrdiff_t stride)
  199. {
  200.     ff_put_pixels16_xy2_mmx(dst, src, stride, 16);
  201. }
  202. static void avg_rv40_qpel8_mc33_mmx(uint8_t *dst, uint8_t *src,
  203.                                     ptrdiff_t stride)
  204. {
  205.     ff_avg_pixels8_xy2_mmx(dst, src, stride, 8);
  206. }
  207. static void avg_rv40_qpel16_mc33_mmx(uint8_t *dst, uint8_t *src,
  208.                                      ptrdiff_t stride)
  209. {
  210.     ff_avg_pixels16_xy2_mmx(dst, src, stride, 16);
  211. }
  212. #endif /* HAVE_MMX_INLINE */
  213.  
  214. av_cold void ff_rv40dsp_init_x86(RV34DSPContext *c)
  215. {
  216.     int cpu_flags = av_get_cpu_flags();
  217.  
  218. #if HAVE_MMX_INLINE
  219.     if (INLINE_MMX(cpu_flags)) {
  220.         c->put_pixels_tab[0][15] = put_rv40_qpel16_mc33_mmx;
  221.         c->put_pixels_tab[1][15] = put_rv40_qpel8_mc33_mmx;
  222.         c->avg_pixels_tab[0][15] = avg_rv40_qpel16_mc33_mmx;
  223.         c->avg_pixels_tab[1][15] = avg_rv40_qpel8_mc33_mmx;
  224.     }
  225. #endif /* HAVE_MMX_INLINE */
  226.  
  227. #if HAVE_YASM
  228.     if (EXTERNAL_MMX(cpu_flags)) {
  229.         c->put_chroma_pixels_tab[0] = ff_put_rv40_chroma_mc8_mmx;
  230.         c->put_chroma_pixels_tab[1] = ff_put_rv40_chroma_mc4_mmx;
  231. #if ARCH_X86_32
  232.         QPEL_MC_SET(put_, _mmx)
  233. #endif
  234.     }
  235.     if (EXTERNAL_AMD3DNOW(cpu_flags)) {
  236.         c->avg_chroma_pixels_tab[0] = ff_avg_rv40_chroma_mc8_3dnow;
  237.         c->avg_chroma_pixels_tab[1] = ff_avg_rv40_chroma_mc4_3dnow;
  238. #if ARCH_X86_32
  239.         QPEL_MC_SET(avg_, _3dnow)
  240. #endif
  241.     }
  242.     if (EXTERNAL_MMXEXT(cpu_flags)) {
  243.         c->avg_chroma_pixels_tab[0]     = ff_avg_rv40_chroma_mc8_mmxext;
  244.         c->avg_chroma_pixels_tab[1]     = ff_avg_rv40_chroma_mc4_mmxext;
  245.         c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_rnd_16_mmxext;
  246.         c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_mmxext;
  247.         c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_mmxext;
  248.         c->rv40_weight_pixels_tab[1][1] = ff_rv40_weight_func_nornd_8_mmxext;
  249. #if ARCH_X86_32
  250.         QPEL_MC_SET(avg_, _mmxext)
  251. #endif
  252.     }
  253.     if (EXTERNAL_SSE2(cpu_flags)) {
  254.         c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_rnd_16_sse2;
  255.         c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_sse2;
  256.         c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_sse2;
  257.         c->rv40_weight_pixels_tab[1][1] = ff_rv40_weight_func_nornd_8_sse2;
  258.         QPEL_MC_SET(put_, _sse2)
  259.         QPEL_MC_SET(avg_, _sse2)
  260.     }
  261.     if (EXTERNAL_SSSE3(cpu_flags)) {
  262.         c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_rnd_16_ssse3;
  263.         c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_ssse3;
  264.         c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_ssse3;
  265.         c->rv40_weight_pixels_tab[1][1] = ff_rv40_weight_func_nornd_8_ssse3;
  266.         QPEL_MC_SET(put_, _ssse3)
  267.         QPEL_MC_SET(avg_, _ssse3)
  268.     }
  269. #endif /* HAVE_YASM */
  270. }
  271.