Add support for disabling CLPF on tile boundaries

Change-Id: Icb578f9b54c4020effa4b9245e343c1519bd7acb
diff --git a/aom_dsp/aom_dsp_rtcd_defs.pl b/aom_dsp/aom_dsp_rtcd_defs.pl
index af76fea..a5c492c 100644
--- a/aom_dsp/aom_dsp_rtcd_defs.pl
+++ b/aom_dsp/aom_dsp_rtcd_defs.pl
@@ -6,6 +6,7 @@
 
 #include "aom/aom_integer.h"
 #include "aom_dsp/aom_dsp_common.h"
+#include "av1/common/enums.h"
 
 EOF
 }
@@ -852,7 +853,7 @@
 
 if (aom_config("CONFIG_CLPF") eq "yes") {
   if (aom_config("CONFIG_AOM_HIGHBITDEPTH") eq "yes") {
-    add_proto qw/void aom_clpf_block_hbd/, "const uint16_t *src, uint16_t *dst, int sstride, int dstride, int x0, int y0, int sizex, int sizey, int width, int height, unsigned int strength";
+    add_proto qw/void aom_clpf_block_hbd/, "const uint16_t *src, uint16_t *dst, int sstride, int dstride, int x0, int y0, int sizex, int sizey, unsigned int strength, BOUNDARY_TYPE bt";
     add_proto qw/void aom_clpf_detect_hbd/, "const uint16_t *rec, const uint16_t *org, int rstride, int ostride, int x0, int y0, int width, int height, int *sum0, int *sum1, unsigned int strength, int shift, int size";
     add_proto qw/void aom_clpf_detect_multi_hbd/, "const uint16_t *rec, const uint16_t *org, int rstride, int ostride, int x0, int y0, int width, int height, int *sum, int shift, int size";
     # VS compiling for 32 bit targets does not support vector types in
@@ -864,7 +865,7 @@
       specialize qw/aom_clpf_detect_multi_hbd sse2 ssse3 sse4_1 neon/;
     }
   }
-  add_proto qw/void aom_clpf_block/, "const uint8_t *src, uint8_t *dst, int sstride, int dstride, int x0, int y0, int sizex, int sizey, int width, int height, unsigned int strength";
+  add_proto qw/void aom_clpf_block/, "const uint8_t *src, uint8_t *dst, int sstride, int dstride, int x0, int y0, int sizex, int sizey, unsigned int strength, BOUNDARY_TYPE bt";
   add_proto qw/void aom_clpf_detect/, "const uint8_t *rec, const uint8_t *org, int rstride, int ostride, int x0, int y0, int width, int height, int *sum0, int *sum1, unsigned int strength, int size";
   add_proto qw/void aom_clpf_detect_multi/, "const uint8_t *rec, const uint8_t *org, int rstride, int ostride, int x0, int y0, int width, int height, int *sum, int size";
   # VS compiling for 32 bit targets does not support vector types in
diff --git a/av1/common/clpf.c b/av1/common/clpf.c
index a01e6b4..b1306a3 100644
--- a/av1/common/clpf.c
+++ b/av1/common/clpf.c
@@ -23,17 +23,21 @@
 
 void aom_clpf_block_c(const uint8_t *src, uint8_t *dst, int sstride,
                       int dstride, int x0, int y0, int sizex, int sizey,
-                      int width, int height, unsigned int strength) {
+                      unsigned int strength, BOUNDARY_TYPE bt) {
   int x, y;
+  int xmin = x0 - !(bt & TILE_LEFT_BOUNDARY) * 2;
+  int ymin = y0 - !(bt & TILE_ABOVE_BOUNDARY);
+  int xmax = x0 + sizex + !(bt & TILE_RIGHT_BOUNDARY) * 2 - 1;
+  int ymax = y0 + sizey + !(bt & TILE_BOTTOM_BOUNDARY) - 1;
   for (y = y0; y < y0 + sizey; y++) {
     for (x = x0; x < x0 + sizex; x++) {
       int X = src[y * sstride + x];
-      int A = src[AOMMAX(0, y - 1) * sstride + x];
-      int B = src[y * sstride + AOMMAX(0, x - 2)];
-      int C = src[y * sstride + AOMMAX(0, x - 1)];
-      int D = src[y * sstride + AOMMIN(width - 1, x + 1)];
-      int E = src[y * sstride + AOMMIN(width - 1, x + 2)];
-      int F = src[AOMMIN(height - 1, y + 1) * sstride + x];
+      int A = src[AOMMAX(ymin, y - 1) * sstride + x];
+      int B = src[y * sstride + AOMMAX(xmin, x - 2)];
+      int C = src[y * sstride + AOMMAX(xmin, x - 1)];
+      int D = src[y * sstride + AOMMIN(xmax, x + 1)];
+      int E = src[y * sstride + AOMMIN(xmax, x + 2)];
+      int F = src[AOMMIN(ymax, y + 1) * sstride + x];
       int delta;
       delta = av1_clpf_sample(X, A, B, C, D, E, F, strength);
       dst[y * dstride + x] = X + delta;
@@ -45,17 +49,22 @@
 // Identical to aom_clpf_block_c() apart from "src" and "dst".
 void aom_clpf_block_hbd_c(const uint16_t *src, uint16_t *dst, int sstride,
                           int dstride, int x0, int y0, int sizex, int sizey,
-                          int width, int height, unsigned int strength) {
+                          unsigned int strength, BOUNDARY_TYPE bt) {
   int x, y;
+  int xmin = x0 - !(bt & TILE_LEFT_BOUNDARY) * 2;
+  int ymin = y0 - !(bt & TILE_ABOVE_BOUNDARY);
+  int xmax = x0 + sizex + !(bt & TILE_RIGHT_BOUNDARY) * 2 - 1;
+  int ymax = y0 + sizey + !(bt & TILE_BOTTOM_BOUNDARY) - 1;
+
   for (y = y0; y < y0 + sizey; y++) {
     for (x = x0; x < x0 + sizex; x++) {
       int X = src[y * sstride + x];
-      int A = src[AOMMAX(0, y - 1) * sstride + x];
-      int B = src[y * sstride + AOMMAX(0, x - 2)];
-      int C = src[y * sstride + AOMMAX(0, x - 1)];
-      int D = src[y * sstride + AOMMIN(width - 1, x + 1)];
-      int E = src[y * sstride + AOMMIN(width - 1, x + 2)];
-      int F = src[AOMMIN(height - 1, y + 1) * sstride + x];
+      int A = src[AOMMAX(ymin, y - 1) * sstride + x];
+      int B = src[y * sstride + AOMMAX(xmin, x - 2)];
+      int C = src[y * sstride + AOMMAX(xmin, x - 1)];
+      int D = src[y * sstride + AOMMIN(xmax, x + 1)];
+      int E = src[y * sstride + AOMMIN(xmax, x + 2)];
+      int F = src[AOMMIN(ymax, y + 1) * sstride + x];
       int delta;
       delta = av1_clpf_sample(X, A, B, C, D, E, F, strength);
       dst[y * dstride + x] = X + delta;
@@ -156,6 +165,11 @@
                                      (xpos << subx) / MI_SIZE]
                      ->mbmi.skip ||
                 (enable_fb_flag && fb_size_log2 == MAX_FB_SIZE_LOG2)) {
+              BOUNDARY_TYPE boundary_type =
+                  cm->mi[(ypos << suby) / MI_SIZE * cm->mi_stride +
+                         (xpos << subx) / MI_SIZE]
+                      .mbmi.boundary_info;
+
               // Temporary buffering needed for in-place filtering
               if (cache_ptr[cache_idx]) {
 // Copy filtered block back into the frame
@@ -228,15 +242,15 @@
               if (cm->use_highbitdepth) {
                 aom_clpf_block_hbd(CONVERT_TO_SHORTPTR(src_buffer),
                                    CONVERT_TO_SHORTPTR(dst_buffer), sstride,
-                                   dstride, xpos, ypos, sizex, sizey, width,
-                                   height, strength);
+                                   dstride, xpos, ypos, sizex, sizey, strength,
+                                   boundary_type);
               } else {
                 aom_clpf_block(src_buffer, dst_buffer, sstride, dstride, xpos,
-                               ypos, sizex, sizey, width, height, strength);
+                               ypos, sizex, sizey, strength, boundary_type);
               }
 #else
               aom_clpf_block(src_buffer, dst_buffer, sstride, dstride, xpos,
-                             ypos, sizex, sizey, width, height, strength);
+                             ypos, sizex, sizey, strength, boundary_type);
 #endif
             }
           }
diff --git a/av1/common/clpf_simd.h b/av1/common/clpf_simd.h
index 6fef4b7..7cf9486 100644
--- a/av1/common/clpf_simd.h
+++ b/av1/common/clpf_simd.h
@@ -51,10 +51,12 @@
 
 // Process blocks of width 8, two lines at a time, 8 bit.
 static void clpf_block8(const uint8_t *src, uint8_t *dst, int sstride,
-                        int dstride, int x0, int y0, int sizey, int width,
-                        int height, unsigned int strength) {
-  const int bottom = height - 2 - y0;
-  const int right = width - 8 - x0;
+                        int dstride, int x0, int y0, int sizey,
+                        unsigned int strength, BOUNDARY_TYPE bt) {
+  const int bottom = bt & TILE_BOTTOM_BOUNDARY ? sizey - 2 : -1;
+  const int right = !(bt & TILE_RIGHT_BOUNDARY);
+  const int left = !(bt & TILE_LEFT_BOUNDARY);
+  const int top = bt & TILE_ABOVE_BOUNDARY ? y0 : -1;
   const v128 sp = v128_dup_8(strength);
   const v128 sm = v128_dup_8(-(int)strength);
   DECLARE_ALIGNED(16, static const uint64_t,
@@ -75,12 +77,12 @@
     const v64 l2 = v64_load_aligned(src + sstride);
     v128 o = v128_from_v64(l1, l2);
     const v128 a =
-        v128_from_v64(v64_load_aligned(src - (y != -y0) * sstride), l1);
+        v128_from_v64(v64_load_aligned(src - (y != top) * sstride), l1);
     const v128 f = v128_from_v64(
         l2, v64_load_aligned(src + ((y != bottom) + 1) * sstride));
     v128 b, c, d, e;
 
-    if (x0) {
+    if (left) {
       b = v128_from_v64(v64_load_unaligned(src - 2),
                         v64_load_unaligned(src - 2 + sstride));
       c = v128_from_v64(v64_load_unaligned(src - 1),
@@ -109,12 +111,15 @@
 
 // Process blocks of width 4, four lines at a time, 8 bit.
 static void clpf_block4(const uint8_t *src, uint8_t *dst, int sstride,
-                        int dstride, int x0, int y0, int sizey, int width,
-                        int height, unsigned int strength) {
+                        int dstride, int x0, int y0, int sizey,
+                        unsigned int strength, BOUNDARY_TYPE bt) {
   const v128 sp = v128_dup_8(strength);
   const v128 sm = v128_dup_8(-(int)strength);
-  const int right = width - 4 - x0;
-  const int bottom = height - 4 - y0;
+  const int right = !(bt & TILE_RIGHT_BOUNDARY);
+  const int bottom = bt & TILE_BOTTOM_BOUNDARY ? sizey - 4 : -1;
+  const int left = !(bt & TILE_LEFT_BOUNDARY);
+  const int top = bt & TILE_ABOVE_BOUNDARY ? y0 : -1;
+
   DECLARE_ALIGNED(16, static const uint64_t,
                   b_shuff[]) = { 0x0504040401000000LL, 0x0d0c0c0c09080808LL };
   DECLARE_ALIGNED(16, static const uint64_t,
@@ -129,7 +134,7 @@
   src += x0 + y0 * sstride;
 
   for (y = 0; y < sizey; y += 4) {
-    const uint32_t l0 = u32_load_aligned(src - (y != -y0) * sstride);
+    const uint32_t l0 = u32_load_aligned(src - (y != top) * sstride);
     const uint32_t l1 = u32_load_aligned(src);
     const uint32_t l2 = u32_load_aligned(src + sstride);
     const uint32_t l3 = u32_load_aligned(src + 2 * sstride);
@@ -140,7 +145,7 @@
     const v128 f = v128_from_32(l2, l3, l4, l5);
     v128 b, c, d, e;
 
-    if (x0) {
+    if (left) {
       b = v128_from_32(u32_load_unaligned(src - 2),
                        u32_load_unaligned(src + sstride - 2),
                        u32_load_unaligned(src + 2 * sstride - 2),
@@ -180,17 +185,17 @@
 
 void SIMD_FUNC(aom_clpf_block)(const uint8_t *src, uint8_t *dst, int sstride,
                                int dstride, int x0, int y0, int sizex,
-                               int sizey, int width, int height,
-                               unsigned int strength) {
+                               int sizey, unsigned int strength,
+                               BOUNDARY_TYPE bt) {
   if ((sizex != 4 && sizex != 8) || ((sizey & 3) && sizex == 4)) {
     // Fallback to C for odd sizes:
     // * block widths not 4 or 8
     // * block heights not a multiple of 4 if the block width is 4
-    aom_clpf_block_c(src, dst, sstride, dstride, x0, y0, sizex, sizey, width,
-                     height, strength);
+    aom_clpf_block_c(src, dst, sstride, dstride, x0, y0, sizex, sizey, strength,
+                     bt);
   } else {
     (sizex == 4 ? clpf_block4 : clpf_block8)(src, dst, sstride, dstride, x0, y0,
-                                             sizey, width, height, strength);
+                                             sizey, strength, bt);
   }
 }
 
@@ -237,12 +242,15 @@
 // Process blocks of width 4, two lines at time.
 SIMD_INLINE void clpf_block_hbd4(const uint16_t *src, uint16_t *dst,
                                  int sstride, int dstride, int x0, int y0,
-                                 int sizey, int width, int height,
-                                 unsigned int strength) {
+                                 int sizey, unsigned int strength,
+                                 BOUNDARY_TYPE bt) {
   const v128 sp = v128_dup_16(strength);
   const v128 sm = v128_dup_16(-(int)strength);
-  const int right = width - 4 - x0;
-  const int bottom = height - 2 - y0;
+  const int right = !(bt & TILE_RIGHT_BOUNDARY);
+  const int bottom = bt & TILE_BOTTOM_BOUNDARY ? sizey - 2 : -1;
+  const int left = !(bt & TILE_LEFT_BOUNDARY);
+  const int top = bt & TILE_ABOVE_BOUNDARY ? y0 : -1;
+
   DECLARE_ALIGNED(16, static const uint64_t,
                   b_shuff[]) = { 0x0302010001000100LL, 0x0b0a090809080908LL };
   DECLARE_ALIGNED(16, static const uint64_t,
@@ -261,12 +269,12 @@
     const v64 l2 = v64_load_aligned(src + sstride);
     v128 o = v128_from_v64(l1, l2);
     const v128 a =
-        v128_from_v64(v64_load_aligned(src - (y != -y0) * sstride), l1);
+        v128_from_v64(v64_load_aligned(src - (y != top) * sstride), l1);
     const v128 f = v128_from_v64(
         l2, v64_load_aligned(src + ((y != bottom) + 1) * sstride));
     v128 b, c, d, e;
 
-    if (x0) {
+    if (left) {
       b = v128_from_v64(v64_load_unaligned(src - 2),
                         v64_load_unaligned(src - 2 + sstride));
       c = v128_from_v64(v64_load_unaligned(src - 1),
@@ -293,11 +301,14 @@
 // The most simple case.  Start here if you need to understand the functions.
 SIMD_INLINE void clpf_block_hbd(const uint16_t *src, uint16_t *dst, int sstride,
                                 int dstride, int x0, int y0, int sizey,
-                                int width, int height, unsigned int strength) {
+                                unsigned int strength, BOUNDARY_TYPE bt) {
   const v128 sp = v128_dup_16(strength);
   const v128 sm = v128_dup_16(-(int)strength);
-  const int right = width - 8 - x0;
-  const int bottom = height - 2 - y0;
+  const int right = !(bt & TILE_RIGHT_BOUNDARY);
+  const int bottom = bt & TILE_BOTTOM_BOUNDARY ? sizey - 2 : -2;
+  const int left = !(bt & TILE_LEFT_BOUNDARY);
+  const int top = bt & TILE_ABOVE_BOUNDARY ? y0 : -1;
+
   DECLARE_ALIGNED(16, static const uint64_t,
                   b_shuff[]) = { 0x0302010001000100LL, 0x0b0a090807060504LL };
   DECLARE_ALIGNED(16, static const uint64_t,
@@ -317,11 +328,11 @@
   // instructions doing shift and pad.
   for (y = 0; y < sizey; y++) {
     const v128 o = v128_load_aligned(src);
-    const v128 a = v128_load_aligned(src - (y != -y0) * sstride);
+    const v128 a = v128_load_aligned(src - (y != top) * sstride);
     const v128 f = v128_load_aligned(src + (y - 1 != bottom) * sstride);
     v128 b, c, d, e;
 
-    if (x0) {
+    if (left) {
       b = v128_load_unaligned(src - 2);
       c = v128_load_unaligned(src - 1);
     } else {  // Left clipping
@@ -343,17 +354,17 @@
 
 void SIMD_FUNC(aom_clpf_block_hbd)(const uint16_t *src, uint16_t *dst,
                                    int sstride, int dstride, int x0, int y0,
-                                   int sizex, int sizey, int width, int height,
-                                   unsigned int strength) {
+                                   int sizex, int sizey, unsigned int strength,
+                                   BOUNDARY_TYPE bt) {
   if ((sizex != 4 && sizex != 8) || ((sizey & 1) && sizex == 4)) {
     // Fallback to C for odd sizes:
     // * block width not 4 or 8
     // * block heights not a multiple of 2 if the block width is 4
     aom_clpf_block_hbd_c(src, dst, sstride, dstride, x0, y0, sizex, sizey,
-                         width, height, strength);
+                         strength, bt);
   } else {
     (sizex == 4 ? clpf_block_hbd4 : clpf_block_hbd)(
-        src, dst, sstride, dstride, x0, y0, sizey, width, height, strength);
+        src, dst, sstride, dstride, x0, y0, sizey, strength, bt);
   }
 }
 #endif
diff --git a/test/clpf_test.cc b/test/clpf_test.cc
index 0b00a3d..2e34f45 100644
--- a/test/clpf_test.cc
+++ b/test/clpf_test.cc
@@ -28,7 +28,7 @@
 
 typedef void (*clpf_block_t)(const uint8_t *src, uint8_t *dst, int sstride,
                              int dstride, int x0, int y0, int sizex, int sizey,
-                             int width, int height, unsigned int strength);
+                             unsigned int strength, BOUNDARY_TYPE bt);
 
 typedef std::tr1::tuple<clpf_block_t, clpf_block_t, int, int>
     clpf_block_param_t;
@@ -57,8 +57,8 @@
 #if CONFIG_AOM_HIGHBITDEPTH
 typedef void (*clpf_block_hbd_t)(const uint16_t *src, uint16_t *dst,
                                  int sstride, int dstride, int x0, int y0,
-                                 int sizex, int sizey, int width, int height,
-                                 unsigned int strength);
+                                 int sizex, int sizey, unsigned int strength,
+                                 BOUNDARY_TYPE bt);
 
 typedef std::tr1::tuple<clpf_block_hbd_t, clpf_block_hbd_t, int, int>
     clpf_block_hbd_param_t;
@@ -90,11 +90,11 @@
 void test_clpf(int w, int h, int depth, int iterations,
                void (*clpf)(const pixel *src, pixel *dst, int sstride,
                             int dstride, int x0, int y0, int sizex, int sizey,
-                            int width, int height, unsigned int strength),
+                            unsigned int strength, BOUNDARY_TYPE bt),
                void (*ref_clpf)(const pixel *src, pixel *dst, int sstride,
                                 int dstride, int x0, int y0, int sizex,
-                                int sizey, int width, int height,
-                                unsigned int strength)) {
+                                int sizey, unsigned int strength,
+                                BOUNDARY_TYPE bt)) {
   const int size = 24;
   ACMRandom rnd(ACMRandom::DeterministicSeed());
   DECLARE_ALIGNED(16, pixel, s[size * size]);
@@ -123,11 +123,16 @@
           for (xpos = 0; xpos < size && !error; xpos += w * !error) {
             for (strength = depth - 8; strength < depth - 5 && !error;
                  strength += !error) {
-              ref_clpf(s, ref_d, size, size, xpos, ypos, w, h, size, size,
-                       1 << strength);
+              BOUNDARY_TYPE bt =
+                  BOUNDARY_TYPE((TILE_LEFT_BOUNDARY & -(!xpos)) |
+                                (TILE_ABOVE_BOUNDARY & -(!ypos)) |
+                                (TILE_RIGHT_BOUNDARY & -(xpos + w == size)) |
+                                (TILE_BOTTOM_BOUNDARY & -(ypos + h == size)));
+              ref_clpf(s, ref_d, size, size, xpos, ypos, w, h, 1 << strength,
+                       bt);
               if (clpf != ref_clpf)
                 ASM_REGISTER_STATE_CHECK(clpf(s, d, size, size, xpos, ypos, w,
-                                              h, size, size, 1 << strength));
+                                              h, 1 << strength, bt));
               if (ref_clpf != clpf)
                 for (pos = 0; pos < size * size && !error; pos++) {
                   error = ref_d[pos] != d[pos];
@@ -163,12 +168,12 @@
 void test_clpf_speed(int w, int h, int depth, int iterations,
                      void (*clpf)(const pixel *src, pixel *dst, int sstride,
                                   int dstride, int x0, int y0, int sizex,
-                                  int sizey, int width, int height,
-                                  unsigned int strength),
+                                  int sizey, unsigned int strength,
+                                  BOUNDARY_TYPE bt),
                      void (*ref_clpf)(const pixel *src, pixel *dst, int sstride,
                                       int dstride, int x0, int y0, int sizex,
-                                      int sizey, int width, int height,
-                                      unsigned int strength)) {
+                                      int sizey, unsigned int strength,
+                                      BOUNDARY_TYPE bt)) {
   aom_usec_timer ref_timer;
   aom_usec_timer timer;