[vte/wip/egmont/bidi: 106/107] fine grained gtk invalidate, part 1



commit f504e2c921283b1a4db59b8e2eeb86ed5d24171f
Author: Egmont Koblinger <egmont gmail com>
Date:   Wed May 29 14:34:34 2019 +0200

    fine grained gtk invalidate, part 1

 src/vte.cc         | 127 +++++++++++++++++++++++++++++++++++++----------------
 src/vteinternal.hh |   6 ++-
 src/vteseq.cc      |  26 +++++------
 3 files changed, 106 insertions(+), 53 deletions(-)
---
diff --git a/src/vte.cc b/src/vte.cc
index 7533c77f..eb7c226a 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -245,10 +245,22 @@ Terminal::cursor_is_onscreen() const noexcept
 }
 
 /* Note that end_row is inclusive. This is not as nice as end-exclusive,
- * but saves us from a +1 almost everywhere where this method is called. */
+ * but saves us from a +1 almost everywhere where this method is called.
+ *
+ * If @extend, the region is extended in both directions up to an explicit
+ * newline (or a safety limit) to invalidate entire paragraphs of text.
+ * This is to be used whenever the underlying data changes, because any such
+ * change might alter the desired BiDi, syntax highlighting etc. of all other
+ * rows of the involved paragraph(s).
+ *
+ * If not @extend, only the requested rows are invalidated. This is to be
+ * used when only the desired rendering changes but not the underlying data,
+ * e.g. moving or blinking cursor, highligthing with the mouse etc.
+ */
 void
 Terminal::invalidate_rows(vte::grid::row_t row_start,
-                          vte::grid::row_t row_end /* inclusive */)
+                          vte::grid::row_t row_end /* inclusive */,
+                          bool extend)
 {
        if (G_UNLIKELY (!widget_realized()))
                 return;
@@ -260,24 +272,57 @@ Terminal::invalidate_rows(vte::grid::row_t row_start,
                 return;
 
        _vte_debug_print (VTE_DEBUG_UPDATES,
-                          "Invalidating rows %ld..%ld.\n",
-                          row_start, row_end);
+                          "Invalidating rows %ld..%ld (extend: %s).\n",
+                          row_start, row_end, extend ? "true" : "false");
        _vte_debug_print (VTE_DEBUG_WORK, "?");
 
-        // HACK for BiDi: Always invalidate everything.
-        // In fact we'd need to invalidate the entire implicit paragraph.
-       if (TRUE) {
-               invalidate_all();
-               return;
-       }
+        if (extend) {
+                /* Scrolled back by so much that changes to the writable area
+                 * may not affect the current viewport's rendering. */
+                if (m_screen->insert_delta - VTE_RINGVIEW_PARAGRAPH_LENGTH_MAX > last_displayed_row())
+                        return;
+        } else {
+                /* Scrolled back, visible parts didn't change. */
+                if (row_start > last_displayed_row())
+                        return;
+        }
 
-        /* Scrolled back, visible parts didn't change. */
-        if (row_start > last_displayed_row())
-                return;
+        if (extend) {
+                /* Extending the start is a bit tricky.
+                 *
+                 * First extend it (towards lower numbered indices), but only up to
+                 * insert_delta, which is still guaranteed to be in the ring's memory. */
+               while (row_start > m_screen->insert_delta) {
+                       if (!m_screen->row_data->is_soft_wrapped(row_start - 1))
+                               break;
+                       row_start--;
+               }
+
+                /* If we haven't seen a newline yet, stop walking backwards row by row.
+                 * This is because we might need to access row_stream in order to check
+                 * its wrapped state, a way too expensive operation while processing
+                 * incoming data. Let displaying do extra work instead.
+                 * So just invalidate everything to the top. */
+                if (row_start < m_screen->insert_delta) {
+                        row_start = first_displayed_row();
+                }
+
+                /* Extending the end is simple. Just walk until we go offscreen or
+                 * find an explicit newline. */
+               while (row_end < last_displayed_row()) {
+                       if (!m_screen->row_data->is_soft_wrapped(row_end))
+                               break;
+                       row_end++;
+               }
+
+                _vte_debug_print (VTE_DEBUG_UPDATES,
+                                  "Invalidating rows extended to %ld..%ld.\n",
+                                  row_start, row_end);
+        }
 
-        /* Scrollbar is at default position, all the writable rows changed. */
-        if (row_start == first_displayed_row() &&
-            row_end - row_start + 1 == m_row_count) {
+        /* Recognize if we're already invalidating everything. */
+        if (row_start <= first_displayed_row() &&
+            row_end >= last_displayed_row()) {
                invalidate_all();
                return;
        }
@@ -320,19 +365,21 @@ Terminal::invalidate_rows(vte::grid::row_t row_start,
 
 /* Convenience method */
 void
-Terminal::invalidate_row(vte::grid::row_t row)
+Terminal::invalidate_row(vte::grid::row_t row, bool extend)
 {
-        invalidate_rows(row, row);
+        invalidate_rows(row, row, extend);
 }
 
+/* This is only used by the selection code, so no need to extend the area. */
 void
 Terminal::invalidate(vte::grid::span const& s)
 {
         if (!s.empty())
-                invalidate_rows(s.start_row(), s.last_row());
+                invalidate_rows(s.start_row(), s.last_row(), false);
 }
 
-/* Invalidates the symmetrical difference ("XOR" area) of the two spans */
+/* Invalidates the symmetrical difference ("XOR" area) of the two spans.
+ * This is only used by the selection code, so no need to extend the area. */
 void
 Terminal::invalidate_symmetrical_difference(vte::grid::span const& a, vte::grid::span const& b, bool block)
 {
@@ -346,15 +393,18 @@ Terminal::invalidate_symmetrical_difference(vte::grid::span const& a, vte::grid:
         if (block) {
                 /* We could optimize when the columns don't change, probably not worth it. */
                 invalidate_rows (std::min (a.start_row(), b.start_row()),
-                                 std::max (a.last_row(),  b.last_row()));
+                                 std::max (a.last_row(),  b.last_row()),
+                                 false);
         } else {
                 if (a.start() != b.start()) {
                         invalidate_rows (std::min (a.start_row(), b.start_row()),
-                                         std::max (a.start_row(), b.start_row()));
+                                         std::max (a.start_row(), b.start_row()),
+                                         false);
                 }
                 if (a.end() != b.end()) {
                         invalidate_rows (std::min (a.last_row(), b.last_row()),
-                                         std::max (a.last_row(), b.last_row()));
+                                         std::max (a.last_row(), b.last_row()),
+                                         false);
                 }
         }
 }
@@ -545,7 +595,7 @@ Terminal::invalidate_cursor_once(bool periodic)
                _vte_debug_print(VTE_DEBUG_UPDATES,
                                  "Invalidating cursor in row %ld.\n",
                                  row);
-                invalidate_row(row);
+                invalidate_row(row, false);
        }
 }
 
@@ -2667,7 +2717,7 @@ Terminal::cleanup_fragments(long start,
                         cell_end->c = ' ';
                         cell_end->attr.set_fragment(false);
                         cell_end->attr.set_columns(1);
-                        invalidate_row(m_screen->cursor.row);
+                        invalidate_row(m_screen->cursor.row, false);
                 }
         }
 
@@ -2691,7 +2741,7 @@ Terminal::cleanup_fragments(long start,
                                                          "Cleaning CJK left half at %ld\n",
                                                          col);
                                         g_assert(start - col == 1);
-                                        invalidate_row(m_screen->cursor.row);
+                                        invalidate_row(m_screen->cursor.row, false);
                                 }
                                 keep_going = FALSE;
                         }
@@ -2730,7 +2780,7 @@ Terminal::cursor_down(bool explicit_sequence)
                                 ring_insert(m_screen->cursor.row, false);
                                /* Force the areas below the region to be
                                 * redrawn -- they've moved. */
-                                invalidate_rows(start, end);
+                                invalidate_rows(start, end, true /* FIXME */);
                                /* Force scroll. */
                                adjust_adjustments();
                        } else {
@@ -2740,7 +2790,7 @@ Terminal::cursor_down(bool explicit_sequence)
                                ring_remove(start);
                                ring_insert(end, true);
                                /* Update the display. */
-                                invalidate_rows(start, end);
+                                invalidate_rows(start, end, true /* FIXME */);
                        }
                } else {
                        /* Scroll up with history. */
@@ -2977,7 +3027,7 @@ Terminal::insert_char(gunichar c,
                /* Always invalidate since we put the mark on the *previous* cell
                 * and the higher level code doesn't know this. */
                 // FIXMEegmont could this be cleaned up now that we invalidate rows?
-                invalidate_row(row_num);
+                invalidate_row(row_num, true);
 
                goto done;
         } else {
@@ -3022,7 +3072,7 @@ Terminal::insert_char(gunichar c,
 
        /* Signal that this part of the window needs drawing. */
        if (G_UNLIKELY (invalidate_now)) {
-                invalidate_row(m_screen->cursor.row);
+                invalidate_row(m_screen->cursor.row, true);
        }
 
         m_screen->cursor.col = col;
@@ -3067,7 +3117,7 @@ Terminal::apply_bidi_attributes(vte::grid::row_t row, guint8 bidi_flags, guint8
                 rowdata->attr.bidi_flags &= ~bidi_flags_mask;
                 rowdata->attr.bidi_flags |= bidi_flags;
 
-                invalidate_row(row);
+                invalidate_row(row, false /* ugly */);
                 if (!rowdata->attr.soft_wrapped)
                         return;
                 row++;
@@ -3748,7 +3798,7 @@ Terminal::process_incoming()
                                                         bbox_top = std::max(bbox_top, top_row);
                                                         bbox_bottom = std::min(bbox_bottom, bottom_row);
 
-                                                        invalidate_rows(bbox_top, bbox_bottom);
+                                                        invalidate_rows(bbox_top, bbox_bottom, true);
                                                         bbox_bottom = -G_MAXINT;
                                                         bbox_top = G_MAXINT;
 
@@ -3810,7 +3860,7 @@ Terminal::process_incoming()
                                                 bbox_top = std::max(bbox_top, top_row);
                                                 bbox_bottom = std::min(bbox_bottom, bottom_row);
 
-                                                invalidate_rows(bbox_top, bbox_bottom);
+                                                invalidate_rows(bbox_top, bbox_bottom, true);
 
                                                 invalidated_text = FALSE;
                                                 bbox_bottom = -G_MAXINT;
@@ -3877,21 +3927,21 @@ Terminal::process_incoming()
                 bbox_top = std::max(bbox_top, top_row);
                 bbox_bottom = std::min(bbox_bottom, bottom_row);
 
-                invalidate_rows(bbox_top, bbox_bottom);
+                invalidate_rows(bbox_top, bbox_bottom, true);
        }
 
         if ((saved_cursor.col != m_screen->cursor.col) ||
             (saved_cursor.row != m_screen->cursor.row)) {
                /* invalidate the old and new cursor positions */
                if (saved_cursor_visible)
-                        invalidate_row(saved_cursor.row);
+                        invalidate_row(saved_cursor.row, false);
                invalidate_cursor_once();
                check_cursor_blink();
                /* Signal that the cursor moved. */
                queue_cursor_moved();
         } else if ((saved_cursor_visible != m_modes_private.DEC_TEXT_CURSOR()) ||
                    (saved_cursor_style != m_cursor_style)) {
-                invalidate_row(saved_cursor.row);
+                invalidate_row(saved_cursor.row, false);
                check_cursor_blink();
        }
 
@@ -5896,7 +5946,7 @@ Terminal::hyperlink_invalidate_and_get_bbox(vte::base::Ring::hyperlink_idx_t idx
                                 }
                         }
                         if (G_UNLIKELY (do_invalidate_row)) {
-                                invalidate_row(row);
+                                invalidate_row(row, false);
                         }
                 }
         }
@@ -6021,6 +6071,7 @@ Terminal::match_hilite_clear()
        }
 }
 
+/* This is only used by the dingu matching code, so no need to extend the area. */
 void
 Terminal::invalidate_match_span()
 {
@@ -10353,7 +10404,7 @@ Terminal::select_text(vte::grid::column_t start_col,
         widget_copy(VTE_SELECTION_PRIMARY, VTE_FORMAT_TEXT);
        emit_selection_changed();
 
-        invalidate_rows(start_row, end_row);
+        invalidate_rows(start_row, end_row, false);
 }
 
 void
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index d535223c..f5eb7faa 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -662,9 +662,11 @@ public:
                          bool insert,
                          bool invalidate_now);
 
-        void invalidate_row(vte::grid::row_t row);
+        void invalidate_row(vte::grid::row_t row,
+                            bool extend);
         void invalidate_rows(vte::grid::row_t row_start,
-                             vte::grid::row_t row_end /* inclusive */);
+                             vte::grid::row_t row_end /* inclusive */,
+                             bool extend);
         void invalidate(vte::grid::span const& s);
         void invalidate_symmetrical_difference(vte::grid::span const& a, vte::grid::span const& b, bool 
block);
         void invalidate_match_span();
diff --git a/src/vteseq.cc b/src/vteseq.cc
index d5b18b23..094b4020 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -317,7 +317,7 @@ Terminal::clear_current_line()
                rowdata->attr.soft_wrapped = 0;
                 rowdata->attr.bidi_flags = get_bidi_flags();
                /* Repaint this row. */
-                invalidate_row(m_screen->cursor.row);
+                invalidate_row(m_screen->cursor.row, false /* FIXME */);
        }
 
        /* We've modified the display.  Make a note of it. */
@@ -332,7 +332,7 @@ Terminal::clear_above_current()
         if (m_screen->insert_delta > _vte_ring_delta(m_screen->row_data)) {
                 auto rowdata = _vte_ring_index_writable(m_screen->row_data, m_screen->insert_delta - 1);
                 rowdata->attr.soft_wrapped = 0;
-                invalidate_row(m_screen->insert_delta - 1);  // FIXME
+                invalidate_row(m_screen->insert_delta - 1, false /* FIXME */);  // FIXME
         }
        /* If the cursor is actually on the screen, clear data in the row
         * which corresponds to the cursor. */
@@ -348,7 +348,7 @@ Terminal::clear_above_current()
                        rowdata->attr.soft_wrapped = 0;
                         rowdata->attr.bidi_flags = get_bidi_flags();
                        /* Repaint the row. */
-                        invalidate_row(i);
+                        invalidate_row(i, false /* FIXME */);
                }
        }
        /* We've modified the display.  Make a note of it. */
@@ -384,7 +384,7 @@ Terminal::scroll_text(vte::grid::row_t scroll_amount)
        }
 
        /* Update the display. */
-        invalidate_rows(start, end);
+        invalidate_rows(start, end, true /* FIXME */);
 
        /* Adjust the scrollbars if necessary. */
         adjust_adjustments();
@@ -707,7 +707,7 @@ Terminal::clear_to_bol()
                }
        }
        /* Repaint this row. */
-        invalidate_row(m_screen->cursor.row);
+        invalidate_row(m_screen->cursor.row, true);
 
        /* We've modified the display.  Make a note of it. */
         m_text_deleted_flag = TRUE;
@@ -764,7 +764,7 @@ Terminal::clear_below_current()
                if (i > m_screen->cursor.row)
                         rowdata->attr.bidi_flags = get_bidi_flags();
                /* Repaint this row. */
-                invalidate_row(i);
+                invalidate_row(i, true /* FIXME */);
        }
 
        /* We've modified the display.  Make a note of it. */
@@ -803,7 +803,7 @@ Terminal::clear_to_eol()
        }
        rowdata->attr.soft_wrapped = 0;
        /* Repaint this row. */
-        invalidate_row(m_screen->cursor.row);
+        invalidate_row(m_screen->cursor.row, true /* FIXME */);
 }
 
 /*
@@ -935,7 +935,7 @@ Terminal::delete_character()
                        }
                         rowdata->attr.soft_wrapped = 0;
                        /* Repaint this row. */
-                        invalidate_row(m_screen->cursor.row);
+                        invalidate_row(m_screen->cursor.row, true /* FIXME */);
                }
        }
 
@@ -993,7 +993,7 @@ Terminal::erase_characters(long count)
                        }
                }
                /* Repaint this row. */
-                invalidate_row(m_screen->cursor.row);
+                invalidate_row(m_screen->cursor.row, true);
        }
 
        /* We've modified the display.  Make a note of it. */
@@ -1108,7 +1108,7 @@ Terminal::move_cursor_tab_forward(int count)
                 }
         }
 
-        invalidate_row(m_screen->cursor.row);
+        invalidate_row(m_screen->cursor.row, false);
         m_screen->cursor.col = newcol;
 }
 
@@ -1324,7 +1324,7 @@ Terminal::insert_lines(vte::grid::row_t param)
        }
         m_screen->cursor.col = 0;
        /* Update the display. */
-        invalidate_rows(row, end);
+        invalidate_rows(row, end, true /* FIXME */);
        /* Adjust the scrollbars if necessary. */
         adjust_adjustments();
        /* We've modified the display.  Make a note of it. */
@@ -1359,7 +1359,7 @@ Terminal::delete_lines(vte::grid::row_t param)
        }
         m_screen->cursor.col = 0;
        /* Update the display. */
-        invalidate_rows(row, end);
+        invalidate_rows(row, end, true /* FIXME */);
        /* Adjust the scrollbars if necessary. */
         adjust_adjustments();
        /* We've modified the display.  Make a note of it. */
@@ -6753,7 +6753,7 @@ Terminal::RI(vte::parser::Sequence const& seq)
                ring_remove(end);
                ring_insert(start, true);
                /* Update the display. */
-                invalidate_rows(start, end);
+                invalidate_rows(start, end, true /* FIXME */);
        } else {
                /* Otherwise, just move the cursor up. */
                 m_screen->cursor.row--;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]