about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-08-29 23:50:29 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-08-29 23:51:18 -0700
commit930e9eae27f354b5ddeda212231b89314cc2802e (patch)
tree172e2187da8997ac83c2f9ebdd2211a9335c8124
parent5cde7d513e7c228dba61729ae1c25b2e119fb5f8 (diff)
downloadmu-930e9eae27f354b5ddeda212231b89314cc2802e.tar.gz
2113 - stop updating entire screen on tb_present()
Mu still isn't so optimized that I can be profligate with spare cycles.
Instead we'll follow termbox-go's example and create a new API routine
called tb_sync() (after discussion with termbox's author). Now we only
need use tb_sync() on ctrl-l. For everything else use the optimized
render.

Now I think I've eradicated all signs of "cursor thrashing" during
refresh, in spite of how slow mu is as an interpreted language. We only
render the whole screen in some situations, and only if there's no more
input, and even then we only refresh the parts of the screen that
changed.

Thanks Jack and Caleb Couch for providing the impetus behind commits
2109-2113.

I've been lazy about writing tests for all this, but it's still good to
know I could, if I wanted to.
-rw-r--r--070display.cc10
-rw-r--r--071print.mu10
-rw-r--r--termbox/termbox.c9
-rw-r--r--termbox/termbox.h3
4 files changed, 32 insertions, 0 deletions
diff --git a/070display.cc b/070display.cc
index 2c52534e..8c02bc57 100644
--- a/070display.cc
+++ b/070display.cc
@@ -49,6 +49,16 @@ case CLEAR_DISPLAY: {
 }
 
 :(before "End Primitive Recipe Declarations")
+SYNC_DISPLAY,
+:(before "End Primitive Recipe Numbers")
+Recipe_ordinal["sync-display"] = SYNC_DISPLAY;
+:(before "End Primitive Recipe Implementations")
+case SYNC_DISPLAY: {
+  tb_sync();
+  break;
+}
+
+:(before "End Primitive Recipe Declarations")
 CLEAR_LINE_ON_DISPLAY,
 :(before "End Primitive Recipe Numbers")
 Recipe_ordinal["clear-line-on-display"] = CLEAR_LINE_ON_DISPLAY;
diff --git a/071print.mu b/071print.mu
index 186f5913..6aeb2042 100644
--- a/071print.mu
+++ b/071print.mu
@@ -65,6 +65,16 @@ recipe clear-screen [
   reply sc/same-as-ingredient:0
 ]
 
+recipe sync-screen [
+  local-scope
+  sc:address:screen <- next-ingredient
+  {
+    break-if sc
+    sync-display
+  }
+  # do nothing for fake screens
+]
+
 recipe fake-screen-is-empty? [
   local-scope
   sc:address:screen <- next-ingredient
diff --git a/termbox/termbox.c b/termbox/termbox.c
index c9ea6012..76d43753 100644
--- a/termbox/termbox.c
+++ b/termbox/termbox.c
@@ -181,6 +181,10 @@ void tb_present(void)
       front = &CELL(&front_buffer, x, y);
       w = wcwidth(back->ch);
       if (w < 1) w = 1;
+      if (memcmp(back, front, sizeof(struct tb_cell)) == 0) {
+        x += w;
+        continue;
+      }
       memcpy(front, back, sizeof(struct tb_cell));
       send_attr(back->fg, back->bg);
       if (w > 1 && x >= front_buffer.width - (w - 1)) {
@@ -205,6 +209,11 @@ void tb_present(void)
   bytebuffer_flush(&output_buffer, inout);
 }
 
+void tb_sync(void) {
+  cellbuf_clear(&front_buffer);
+  tb_present();
+}
+
 void tb_set_cursor(int cx, int cy)
 {
   assert(termw != -1);
diff --git a/termbox/termbox.h b/termbox/termbox.h
index c629b01c..a94d2b85 100644
--- a/termbox/termbox.h
+++ b/termbox/termbox.h
@@ -49,6 +49,9 @@ int tb_height(void);
  * tb_present(). */
 void tb_present(void);
 
+/* Variant of tb_present() that always refreshes the entire screen. */
+void tb_sync(void);
+
 /* Returns a pointer to the internal screen state: a 1D array of cells in
  * raster order. You'll need to call tb_width() and tb_height() for the
  * array's dimensions. The array stays valid until tb_clear() or tb_present()