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
extend_plane(uint8_t * const src,int src_stride,int width,int height,int extend_top,int extend_left,int extend_bottom,int extend_right)19 static 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 
extend_frame(YV12_BUFFER_CONFIG * const ybf,int subsampling_x,int subsampling_y,int ext_size)107 static void extend_frame(YV12_BUFFER_CONFIG *const ybf,
108                          int subsampling_x, int subsampling_y,
109                          int ext_size) {
110   const int c_w = ybf->uv_crop_width;
111   const int c_h = ybf->uv_crop_height;
112   const int c_ext_size = ext_size >> 1;
113   const int c_et = c_ext_size;
114   const int c_el = c_ext_size;
115   const int c_eb = c_ext_size + ybf->uv_height - ybf->uv_crop_height;
116   const int c_er = c_ext_size + ybf->uv_width - ybf->uv_crop_width;
117 
118   assert(ybf->y_height - ybf->y_crop_height < 16);
119   assert(ybf->y_width - ybf->y_crop_width < 16);
120   assert(ybf->y_height - ybf->y_crop_height >= 0);
121   assert(ybf->y_width - ybf->y_crop_width >= 0);
122 
123   extend_plane(ybf->y_buffer, ybf->y_stride,
124                ybf->y_crop_width, ybf->y_crop_height,
125                ext_size, ext_size,
126                ext_size + ybf->y_height - ybf->y_crop_height,
127                ext_size + ybf->y_width - ybf->y_crop_width);
128 
129   extend_plane(ybf->u_buffer, ybf->uv_stride,
130                c_w, c_h, c_et, c_el, c_eb, c_er);
131 
132   extend_plane(ybf->v_buffer, ybf->uv_stride,
133                c_w, c_h, c_et, c_el, c_eb, c_er);
134 }
135 
vp9_extend_frame_borders_dspr2(YV12_BUFFER_CONFIG * ybf,int subsampling_x,int subsampling_y)136 void vp9_extend_frame_borders_dspr2(YV12_BUFFER_CONFIG *ybf,
137                                 int subsampling_x, int subsampling_y) {
138   extend_frame(ybf, subsampling_x, subsampling_y, ybf->border);
139 }
140 
vp9_extend_frame_inner_borders_dspr2(YV12_BUFFER_CONFIG * ybf,int subsampling_x,int subsampling_y)141 void vp9_extend_frame_inner_borders_dspr2(YV12_BUFFER_CONFIG *ybf,
142                                           int subsampling_x,
143                                           int subsampling_y) {
144   const int inner_bw = (ybf->border > VP9INNERBORDERINPIXELS) ?
145                        VP9INNERBORDERINPIXELS : ybf->border;
146   extend_frame(ybf, subsampling_x, subsampling_y, inner_bw);
147 }
148 #endif
149