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, int width,
20 int height, int extend_top, int extend_left,
21 int extend_bottom, int extend_right) {
22 int i, j;
23 uint8_t *left_src, *right_src;
24 uint8_t *left_dst_start, *right_dst_start;
25 uint8_t *left_dst, *right_dst;
26 uint8_t *top_src, *bot_src;
27 uint8_t *top_dst, *bot_dst;
28 uint32_t left_pix;
29 uint32_t right_pix;
30 uint32_t linesize;
31
32 /* copy the left and right most columns out */
33 left_src = src;
34 right_src = src + width - 1;
35 left_dst_start = src - extend_left;
36 right_dst_start = src + width;
37
38 for (i = height; i--;) {
39 left_dst = left_dst_start;
40 right_dst = right_dst_start;
41
42 __asm__ __volatile__(
43 "lb %[left_pix], 0(%[left_src]) \n\t"
44 "lb %[right_pix], 0(%[right_src]) \n\t"
45 "replv.qb %[left_pix], %[left_pix] \n\t"
46 "replv.qb %[right_pix], %[right_pix] \n\t"
47
48 : [left_pix] "=&r"(left_pix), [right_pix] "=&r"(right_pix)
49 : [left_src] "r"(left_src), [right_src] "r"(right_src));
50
51 for (j = extend_left / 4; j--;) {
52 __asm__ __volatile__(
53 "sw %[left_pix], 0(%[left_dst]) \n\t"
54 "sw %[right_pix], 0(%[right_dst]) \n\t"
55
56 :
57 : [left_dst] "r"(left_dst), [left_pix] "r"(left_pix),
58 [right_dst] "r"(right_dst), [right_pix] "r"(right_pix));
59
60 left_dst += 4;
61 right_dst += 4;
62 }
63
64 for (j = extend_left % 4; j--;) {
65 __asm__ __volatile__(
66 "sb %[left_pix], 0(%[left_dst]) \n\t"
67 "sb %[right_pix], 0(%[right_dst]) \n\t"
68
69 :
70 : [left_dst] "r"(left_dst), [left_pix] "r"(left_pix),
71 [right_dst] "r"(right_dst), [right_pix] "r"(right_pix));
72
73 left_dst += 1;
74 right_dst += 1;
75 }
76
77 left_src += src_stride;
78 right_src += src_stride;
79 left_dst_start += src_stride;
80 right_dst_start += src_stride;
81 }
82
83 /* Now copy the top and bottom lines into each line of the respective
84 * borders
85 */
86 top_src = src - extend_left;
87 bot_src = src + src_stride * (height - 1) - extend_left;
88 top_dst = src + src_stride * (-extend_top) - extend_left;
89 bot_dst = src + src_stride * (height)-extend_left;
90 linesize = extend_left + extend_right + width;
91
92 for (i = 0; i < extend_top; i++) {
93 memcpy(top_dst, top_src, linesize);
94 top_dst += src_stride;
95 }
96
97 for (i = 0; i < extend_bottom; i++) {
98 memcpy(bot_dst, bot_src, linesize);
99 bot_dst += src_stride;
100 }
101 }
102
extend_frame(YV12_BUFFER_CONFIG * const ybf,int ext_size)103 static void extend_frame(YV12_BUFFER_CONFIG *const ybf, int ext_size) {
104 const int c_w = ybf->uv_crop_width;
105 const int c_h = ybf->uv_crop_height;
106 const int ss_x = ybf->uv_width < ybf->y_width;
107 const int ss_y = ybf->uv_height < ybf->y_height;
108 const int c_et = ext_size >> ss_y;
109 const int c_el = ext_size >> ss_x;
110 const int c_eb = c_et + ybf->uv_height - ybf->uv_crop_height;
111 const int c_er = c_el + ybf->uv_width - ybf->uv_crop_width;
112
113 assert(ybf->y_height - ybf->y_crop_height < 16);
114 assert(ybf->y_width - ybf->y_crop_width < 16);
115 assert(ybf->y_height - ybf->y_crop_height >= 0);
116 assert(ybf->y_width - ybf->y_crop_width >= 0);
117
118 extend_plane(ybf->y_buffer, ybf->y_stride, ybf->y_crop_width,
119 ybf->y_crop_height, ext_size, ext_size,
120 ext_size + ybf->y_height - ybf->y_crop_height,
121 ext_size + ybf->y_width - ybf->y_crop_width);
122
123 extend_plane(ybf->u_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb, c_er);
124
125 extend_plane(ybf->v_buffer, ybf->uv_stride, c_w, c_h, c_et, c_el, c_eb, c_er);
126 }
127
vpx_extend_frame_borders_dspr2(YV12_BUFFER_CONFIG * ybf)128 void vpx_extend_frame_borders_dspr2(YV12_BUFFER_CONFIG *ybf) {
129 extend_frame(ybf, ybf->border);
130 }
131
vpx_extend_frame_inner_borders_dspr2(YV12_BUFFER_CONFIG * ybf)132 void vpx_extend_frame_inner_borders_dspr2(YV12_BUFFER_CONFIG *ybf) {
133 const int inner_bw = (ybf->border > VP9INNERBORDERINPIXELS)
134 ? VP9INNERBORDERINPIXELS
135 : ybf->border;
136 extend_frame(ybf, inner_bw);
137 }
138 #endif
139