Evaluate intra predictor parameters conditionally

This CL checks for the availability of top right and bottom left
neighbour samples for intra predictors only if the same are needed
by the mode being evaluated.

For AVIF still-image encode,

             Encode Time
cpu-used     Reduction(%)
   6            1.811
   7            2.826
   8            2.300
   9            1.948

Change-Id: I377f8aa4b2171b001b67f9ad9b71f2ccfd10743d
diff --git a/av1/common/reconintra.c b/av1/common/reconintra.c
index 7d64dfa..6b1cf36 100644
--- a/av1/common/reconintra.c
+++ b/av1/common/reconintra.c
@@ -1132,7 +1132,7 @@
 #if CONFIG_AV1_HIGHBITDEPTH
 static void build_intra_predictors_high(
     const uint8_t *ref8, int ref_stride, uint8_t *dst8, int dst_stride,
-    PREDICTION_MODE mode, int angle_delta, FILTER_INTRA_MODE filter_intra_mode,
+    PREDICTION_MODE mode, int p_angle, FILTER_INTRA_MODE filter_intra_mode,
     TX_SIZE tx_size, int disable_edge_filter, int n_top_px, int n_topright_px,
     int n_left_px, int n_bottomleft_px, int intra_edge_filter_type,
     int bit_depth) {
@@ -1150,7 +1150,6 @@
   int need_above_left = extend_modes[mode] & NEED_ABOVELEFT;
   const uint16_t *above_ref = ref - ref_stride;
   const uint16_t *left_ref = ref - 1;
-  int p_angle = 0;
   const int is_dr_mode = av1_is_directional_mode(mode);
   const int use_filter_intra = filter_intra_mode != FILTER_INTRA_MODES;
   int base = 128 << (bit_depth - 8);
@@ -1169,7 +1168,6 @@
   // base+1   G      H  ..     S      T      T      T      T      T
 
   if (is_dr_mode) {
-    p_angle = mode_to_angle_map[mode] + angle_delta;
     if (p_angle <= 90)
       need_above = 1, need_left = 0, need_above_left = 1;
     else if (p_angle < 180)
@@ -1180,9 +1178,9 @@
   if (use_filter_intra) need_left = need_above = need_above_left = 1;
 
   assert(n_top_px >= 0);
-  assert(n_topright_px >= 0);
+  assert(n_topright_px >= -1);
   assert(n_left_px >= 0);
-  assert(n_bottomleft_px >= 0);
+  assert(n_bottomleft_px >= -1);
 
   if ((!need_above && n_left_px == 0) || (!need_left && n_top_px == 0)) {
     int val;
@@ -1200,14 +1198,12 @@
 
   // NEED_LEFT
   if (need_left) {
-    int need_bottom = extend_modes[mode] & NEED_BOTTOMLEFT;
-    if (use_filter_intra) need_bottom = 0;
-    if (is_dr_mode) need_bottom = p_angle > 180;
-    const int num_left_pixels_needed = txhpx + (need_bottom ? txwpx : 0);
+    const int num_left_pixels_needed =
+        txhpx + (n_bottomleft_px >= 0 ? txwpx : 0);
     i = 0;
     if (n_left_px > 0) {
       for (; i < n_left_px; i++) left_col[i] = left_ref[i * ref_stride];
-      if (need_bottom && n_bottomleft_px > 0) {
+      if (n_bottomleft_px > 0) {
         assert(i == txhpx);
         for (; i < txhpx + n_bottomleft_px; i++)
           left_col[i] = left_ref[i * ref_stride];
@@ -1221,14 +1217,11 @@
 
   // NEED_ABOVE
   if (need_above) {
-    int need_right = extend_modes[mode] & NEED_ABOVERIGHT;
-    if (use_filter_intra) need_right = 0;
-    if (is_dr_mode) need_right = p_angle < 90;
-    const int num_top_pixels_needed = txwpx + (need_right ? txhpx : 0);
+    const int num_top_pixels_needed = txwpx + (n_topright_px >= 0 ? txhpx : 0);
     if (n_top_px > 0) {
       memcpy(above_row, above_ref, n_top_px * sizeof(above_ref[0]));
       i = n_top_px;
-      if (need_right && n_topright_px > 0) {
+      if (n_topright_px > 0) {
         assert(n_top_px == txwpx);
         memcpy(above_row + txwpx, above_ref + txwpx,
                n_topright_px * sizeof(above_ref[0]));
@@ -1315,7 +1308,7 @@
 
 static void build_intra_predictors(
     const uint8_t *ref, int ref_stride, uint8_t *dst, int dst_stride,
-    PREDICTION_MODE mode, int angle_delta, FILTER_INTRA_MODE filter_intra_mode,
+    PREDICTION_MODE mode, int p_angle, FILTER_INTRA_MODE filter_intra_mode,
     TX_SIZE tx_size, int disable_edge_filter, int n_top_px, int n_topright_px,
     int n_left_px, int n_bottomleft_px, int intra_edge_filter_type) {
   int i;
@@ -1330,7 +1323,6 @@
   int need_left = extend_modes[mode] & NEED_LEFT;
   int need_above = extend_modes[mode] & NEED_ABOVE;
   int need_above_left = extend_modes[mode] & NEED_ABOVELEFT;
-  int p_angle = 0;
   const int is_dr_mode = av1_is_directional_mode(mode);
   const int use_filter_intra = filter_intra_mode != FILTER_INTRA_MODES;
   // The left_data, above_data buffers must be zeroed to fix some intermittent
@@ -1349,7 +1341,6 @@
   // ..
 
   if (is_dr_mode) {
-    p_angle = mode_to_angle_map[mode] + angle_delta;
     if (p_angle <= 90)
       need_above = 1, need_left = 0, need_above_left = 1;
     else if (p_angle < 180)
@@ -1360,9 +1351,9 @@
   if (use_filter_intra) need_left = need_above = need_above_left = 1;
 
   assert(n_top_px >= 0);
-  assert(n_topright_px >= 0);
+  assert(n_topright_px >= -1);
   assert(n_left_px >= 0);
-  assert(n_bottomleft_px >= 0);
+  assert(n_bottomleft_px >= -1);
 
   if ((!need_above && n_left_px == 0) || (!need_left && n_top_px == 0)) {
     int val;
@@ -1380,14 +1371,12 @@
 
   // NEED_LEFT
   if (need_left) {
-    int need_bottom = extend_modes[mode] & NEED_BOTTOMLEFT;
-    if (use_filter_intra) need_bottom = 0;
-    if (is_dr_mode) need_bottom = p_angle > 180;
-    const int num_left_pixels_needed = txhpx + (need_bottom ? txwpx : 0);
+    const int num_left_pixels_needed =
+        txhpx + (n_bottomleft_px >= 0 ? txwpx : 0);
     i = 0;
     if (n_left_px > 0) {
       for (; i < n_left_px; i++) left_col[i] = left_ref[i * ref_stride];
-      if (need_bottom && n_bottomleft_px > 0) {
+      if (n_bottomleft_px > 0) {
         assert(i == txhpx);
         for (; i < txhpx + n_bottomleft_px; i++)
           left_col[i] = left_ref[i * ref_stride];
@@ -1401,14 +1390,11 @@
 
   // NEED_ABOVE
   if (need_above) {
-    int need_right = extend_modes[mode] & NEED_ABOVERIGHT;
-    if (use_filter_intra) need_right = 0;
-    if (is_dr_mode) need_right = p_angle < 90;
-    const int num_top_pixels_needed = txwpx + (need_right ? txhpx : 0);
+    const int num_top_pixels_needed = txwpx + (n_topright_px >= 0 ? txhpx : 0);
     if (n_top_px > 0) {
       memcpy(above_row, above_ref, n_top_px);
       i = n_top_px;
-      if (need_right && n_topright_px > 0) {
+      if (n_topright_px > 0) {
         assert(n_top_px == txwpx);
         memcpy(above_row + txwpx, above_ref + txwpx, n_topright_px);
         i += n_topright_px;
@@ -1610,33 +1596,58 @@
     bsize = scale_chroma_bsize(bsize, ss_x, ss_y);
   }
 
+  const int is_dr_mode = av1_is_directional_mode(mode);
+  const int use_filter_intra = filter_intra_mode != FILTER_INTRA_MODES;
+  int p_angle = 0;
+  int need_top_right = extend_modes[mode] & NEED_ABOVERIGHT;
+  int need_bottom_left = extend_modes[mode] & NEED_BOTTOMLEFT;
+
+  if (use_filter_intra) {
+    need_top_right = 0;
+    need_bottom_left = 0;
+  }
+  if (is_dr_mode) {
+    p_angle = mode_to_angle_map[mode] + angle_delta;
+    need_top_right = p_angle < 90;
+    need_bottom_left = p_angle > 180;
+  }
+
+  // Possible states for have_top_right(TR) and have_bottom_left(BL)
+  // -1 : TR and BL are not needed
+  //  0 : TR and BL are needed but not available
+  // > 0 : TR and BL are needed and pixels are available
   const int have_top_right =
-      has_top_right(sb_size, bsize, mi_row, mi_col, have_top, right_available,
-                    partition, tx_size, row_off, col_off, ss_x, ss_y);
-  const int have_bottom_left = has_bottom_left(
-      sb_size, bsize, mi_row, mi_col, bottom_available, have_left, partition,
-      tx_size, row_off, col_off, ss_x, ss_y);
+      need_top_right ? has_top_right(sb_size, bsize, mi_row, mi_col, have_top,
+                                     right_available, partition, tx_size,
+                                     row_off, col_off, ss_x, ss_y)
+                     : -1;
+  const int have_bottom_left =
+      need_bottom_left ? has_bottom_left(sb_size, bsize, mi_row, mi_col,
+                                         bottom_available, have_left, partition,
+                                         tx_size, row_off, col_off, ss_x, ss_y)
+                       : -1;
 
   const int disable_edge_filter = !enable_intra_edge_filter;
   const int intra_edge_filter_type = get_intra_edge_filter_type(xd, plane);
 #if CONFIG_AV1_HIGHBITDEPTH
   if (is_cur_buf_hbd(xd)) {
     build_intra_predictors_high(
-        ref, ref_stride, dst, dst_stride, mode, angle_delta, filter_intra_mode,
+        ref, ref_stride, dst, dst_stride, mode, p_angle, filter_intra_mode,
         tx_size, disable_edge_filter, have_top ? AOMMIN(txwpx, xr + txwpx) : 0,
-        have_top_right ? AOMMIN(txwpx, xr) : 0,
+        have_top_right > 0 ? AOMMIN(txwpx, xr) : have_top_right,
         have_left ? AOMMIN(txhpx, yd + txhpx) : 0,
-        have_bottom_left ? AOMMIN(txhpx, yd) : 0, intra_edge_filter_type,
-        xd->bd);
+        have_bottom_left > 0 ? AOMMIN(txhpx, yd) : have_bottom_left,
+        intra_edge_filter_type, xd->bd);
     return;
   }
 #endif
   build_intra_predictors(
-      ref, ref_stride, dst, dst_stride, mode, angle_delta, filter_intra_mode,
+      ref, ref_stride, dst, dst_stride, mode, p_angle, filter_intra_mode,
       tx_size, disable_edge_filter, have_top ? AOMMIN(txwpx, xr + txwpx) : 0,
-      have_top_right ? AOMMIN(txwpx, xr) : 0,
+      have_top_right > 0 ? AOMMIN(txwpx, xr) : have_top_right,
       have_left ? AOMMIN(txhpx, yd + txhpx) : 0,
-      have_bottom_left ? AOMMIN(txhpx, yd) : 0, intra_edge_filter_type);
+      have_bottom_left > 0 ? AOMMIN(txhpx, yd) : have_bottom_left,
+      intra_edge_filter_type);
 }
 
 void av1_predict_intra_block_facade(const AV1_COMMON *cm, MACROBLOCKD *xd,