1/*
2 *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <assert.h>
12
13#include "./vpx_config.h"
14#include "vpx_scale/yv12config.h"
15#include "vpx_mem/vpx_mem.h"
16#include "vpx_scale/vpx_scale.h"
17
18#if HAVE_DSPR2
19static void extend_plane(uint8_t *const src, int src_stride,
20                         int width, int height,
21                         int extend_top, int extend_left,
22                         int extend_bottom, int extend_right) {
23  int       i, j;
24  uint8_t   *left_src, *right_src;
25  uint8_t   *left_dst_start, *right_dst_start;
26  uint8_t   *left_dst, *right_dst;
27  uint8_t   *top_src, *bot_src;
28  uint8_t   *top_dst, *bot_dst;
29  uint32_t  left_pix;
30  uint32_t  right_pix;
31  uint32_t  linesize;
32
33  /* copy the left and right most columns out */
34  left_src  = src;
35  right_src = src + width - 1;
36  left_dst_start = src - extend_left;
37  right_dst_start = src + width;
38
39  for (i = height; i--; ) {
40    left_dst  = left_dst_start;
41    right_dst = right_dst_start;
42
43    __asm__ __volatile__ (
44        "lb        %[left_pix],     0(%[left_src])      \n\t"
45        "lb        %[right_pix],    0(%[right_src])     \n\t"
46        "replv.qb  %[left_pix],     %[left_pix]         \n\t"
47        "replv.qb  %[right_pix],    %[right_pix]        \n\t"
48
49        : [left_pix] "=&r" (left_pix), [right_pix] "=&r" (right_pix)
50        : [left_src] "r" (left_src), [right_src] "r" (right_src)
51    );
52
53    for (j = extend_left/4; j--; ) {
54      __asm__ __volatile__ (
55        "sw     %[left_pix],    0(%[left_dst])     \n\t"
56        "sw     %[right_pix],   0(%[right_dst])    \n\t"
57
58        :
59        : [left_dst] "r" (left_dst), [left_pix] "r" (left_pix),
60          [right_dst] "r" (right_dst), [right_pix] "r" (right_pix)
61      );
62
63      left_dst += 4;
64      right_dst += 4;
65    }
66
67    for (j = extend_left%4; j--; ) {
68      __asm__ __volatile__ (
69        "sb     %[left_pix],    0(%[left_dst])     \n\t"
70        "sb     %[right_pix],   0(%[right_dst])     \n\t"
71
72        :
73        : [left_dst] "r" (left_dst), [left_pix] "r" (left_pix),
74          [right_dst] "r" (right_dst), [right_pix] "r" (right_pix)
75      );
76
77      left_dst += 1;
78      right_dst += 1;
79    }
80
81    left_src  += src_stride;
82    right_src += src_stride;
83    left_dst_start += src_stride;
84    right_dst_start += src_stride;
85  }
86
87  /* Now copy the top and bottom lines into each line of the respective
88   * borders
89   */
90  top_src = src - extend_left;
91  bot_src = src + src_stride * (height - 1) - extend_left;
92  top_dst = src + src_stride * (-extend_top) - extend_left;
93  bot_dst = src + src_stride * (height) - extend_left;
94  linesize = extend_left + extend_right + width;
95
96  for (i = 0; i < extend_top; i++) {
97    vpx_memcpy(top_dst, top_src, linesize);
98    top_dst += src_stride;
99  }
100
101  for (i = 0; i < extend_bottom; i++) {
102    vpx_memcpy(bot_dst, bot_src, linesize);
103    bot_dst += src_stride;
104  }
105}
106
107static void extend_frame(YV12_BUFFER_CONFIG *const ybf, int ext_size) {
108  const int c_w = ybf->uv_crop_width;
109  const int c_h = ybf->uv_crop_height;
110  const int ss_x = ybf->uv_width < ybf->y_width;
111  const int ss_y = ybf->uv_height < ybf->y_height;
112  const int c_et = ext_size >> ss_y;
113  const int c_el = ext_size >> ss_x;
114  const int c_eb = c_et + ybf->uv_height - ybf->uv_crop_height;
115  const int c_er = c_el + ybf->uv_width - ybf->uv_crop_width;
116
117  assert(ybf->y_height - ybf->y_crop_height < 16);
118  assert(ybf->y_width - ybf->y_crop_width < 16);
119  assert(ybf->y_height - ybf->y_crop_height >= 0);
120  assert(ybf->y_width - ybf->y_crop_width >= 0);
121
122  extend_plane(ybf->y_buffer, ybf->y_stride,
123               ybf->y_crop_width, ybf->y_crop_height,
124               ext_size, ext_size,
125               ext_size + ybf->y_height - ybf->y_crop_height,
126               ext_size + ybf->y_width - ybf->y_crop_width);
127
128  extend_plane(ybf->u_buffer, ybf->uv_stride,
129               c_w, c_h, c_et, c_el, c_eb, c_er);
130
131  extend_plane(ybf->v_buffer, ybf->uv_stride,
132               c_w, c_h, c_et, c_el, c_eb, c_er);
133}
134
135void vp9_extend_frame_borders_dspr2(YV12_BUFFER_CONFIG *ybf) {
136  extend_frame(ybf, ybf->border);
137}
138
139void vp9_extend_frame_inner_borders_dspr2(YV12_BUFFER_CONFIG *ybf) {
140  const int inner_bw = (ybf->border > VP9INNERBORDERINPIXELS) ?
141                       VP9INNERBORDERINPIXELS : ybf->border;
142  extend_frame(ybf, inner_bw);
143}
144#endif
145