diff options
author | Aurélien Aptel <aurelien.aptel@gmail.com> | 2012-01-21 23:14:41 +0100 |
---|---|---|
committer | Aurélien Aptel <aurelien.aptel@gmail.com> | 2012-01-21 23:14:41 +0100 |
commit | 96c22e1604704504cef6786714191ed5ffb58725 (patch) | |
tree | 5f76ce8a7e3090c7e88edeb155f5e5755faebf4e | |
parent | 281174445ba2b6e1160b2b7b4490eebb0714eb37 (diff) | |
download | st-patched-96c22e1604704504cef6786714191ed5ffb58725.tar.bz2 st-patched-96c22e1604704504cef6786714191ed5ffb58725.tar.xz st-patched-96c22e1604704504cef6786714191ed5ffb58725.zip |
copy dirty lines to screen, add select() timeout & min time between draw() calls.
* add a timeout value (SELECT_TIMEOUT) of 20ms in the select() call
* wait at least 20ms (DRAW_TIMEOUT) between draw() calls
* only copy dirty lines from the buffer to the screen
what draw() does:
* clears dirty lines in the buffer
* draws the longest same-attributes string of each
dirty line to the buffer with multiple xdraws() call
* copies the current dirty line from buffer to the screen with a single
xcopy() call
this changeset makes st run ~10x faster.
-rw-r--r-- | st.c | 53 |
1 files changed, 44 insertions, 9 deletions
@@ -13,8 +13,10 @@ | |||
13 | #include <sys/ioctl.h> | 13 | #include <sys/ioctl.h> |
14 | #include <sys/select.h> | 14 | #include <sys/select.h> |
15 | #include <sys/stat.h> | 15 | #include <sys/stat.h> |
16 | #include <sys/time.h> | ||
16 | #include <sys/types.h> | 17 | #include <sys/types.h> |
17 | #include <sys/wait.h> | 18 | #include <sys/wait.h> |
19 | #include <time.h> | ||
18 | #include <unistd.h> | 20 | #include <unistd.h> |
19 | #include <X11/Xatom.h> | 21 | #include <X11/Xatom.h> |
20 | #include <X11/Xlib.h> | 22 | #include <X11/Xlib.h> |
@@ -22,9 +24,6 @@ | |||
22 | #include <X11/cursorfont.h> | 24 | #include <X11/cursorfont.h> |
23 | #include <X11/keysym.h> | 25 | #include <X11/keysym.h> |
24 | 26 | ||
25 | #include <sys/time.h> | ||
26 | #include <time.h> | ||
27 | |||
28 | #if defined(__linux) | 27 | #if defined(__linux) |
29 | #include <pty.h> | 28 | #include <pty.h> |
30 | #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) | 29 | #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) |
@@ -50,6 +49,9 @@ | |||
50 | #define XK_NO_MOD UINT_MAX | 49 | #define XK_NO_MOD UINT_MAX |
51 | #define XK_ANY_MOD 0 | 50 | #define XK_ANY_MOD 0 |
52 | 51 | ||
52 | #define SELECT_TIMEOUT (20*1000) /* 20 ms */ | ||
53 | #define DRAW_TIMEOUT (20*1000) /* 20 ms */ | ||
54 | |||
53 | #define SERRNO strerror(errno) | 55 | #define SERRNO strerror(errno) |
54 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) | 56 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) |
55 | #define MAX(a, b) ((a) < (b) ? (b) : (a)) | 57 | #define MAX(a, b) ((a) < (b) ? (b) : (a)) |
@@ -138,6 +140,7 @@ typedef struct { | |||
138 | int ch; /* char height */ | 140 | int ch; /* char height */ |
139 | int cw; /* char width */ | 141 | int cw; /* char width */ |
140 | char state; /* focus, redraw, visible */ | 142 | char state; /* focus, redraw, visible */ |
143 | struct timeval lastdraw; | ||
141 | } XWindow; | 144 | } XWindow; |
142 | 145 | ||
143 | typedef struct { | 146 | typedef struct { |
@@ -179,6 +182,7 @@ static void drawregion(int, int, int, int); | |||
179 | static void execsh(void); | 182 | static void execsh(void); |
180 | static void sigchld(int); | 183 | static void sigchld(int); |
181 | static void run(void); | 184 | static void run(void); |
185 | static int last_draw_too_old(void); | ||
182 | 186 | ||
183 | static void csidump(void); | 187 | static void csidump(void); |
184 | static void csihandle(void); | 188 | static void csihandle(void); |
@@ -214,6 +218,7 @@ static void ttywrite(const char *, size_t); | |||
214 | static void xdraws(char *, Glyph, int, int, int, int); | 218 | static void xdraws(char *, Glyph, int, int, int, int); |
215 | static void xhints(void); | 219 | static void xhints(void); |
216 | static void xclear(int, int, int, int); | 220 | static void xclear(int, int, int, int); |
221 | static void xcopy(int, int, int, int); | ||
217 | static void xdrawcursor(void); | 222 | static void xdrawcursor(void); |
218 | static void xinit(void); | 223 | static void xinit(void); |
219 | static void xloadcols(void); | 224 | static void xloadcols(void); |
@@ -224,7 +229,7 @@ static void xresize(int, int); | |||
224 | static void expose(XEvent *); | 229 | static void expose(XEvent *); |
225 | static void visibility(XEvent *); | 230 | static void visibility(XEvent *); |
226 | static void unmap(XEvent *); | 231 | static void unmap(XEvent *); |
227 | static char* kmap(KeySym, unsigned int state); | 232 | static char* kmap(KeySym, unsigned int); |
228 | static void kpress(XEvent *); | 233 | static void kpress(XEvent *); |
229 | static void cmessage(XEvent *); | 234 | static void cmessage(XEvent *); |
230 | static void resize(XEvent *); | 235 | static void resize(XEvent *); |
@@ -1786,6 +1791,14 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { | |||
1786 | XDrawLine(xw.dpy, xw.buf, dc.gc, winx, winy+1, winx+width-1, winy+1); | 1791 | XDrawLine(xw.dpy, xw.buf, dc.gc, winx, winy+1, winx+width-1, winy+1); |
1787 | } | 1792 | } |
1788 | 1793 | ||
1794 | /* copy buffer pixmap to screen pixmap */ | ||
1795 | void | ||
1796 | xcopy(int x, int y, int cols, int rows) { | ||
1797 | int src_x = x*xw.cw, src_y = y*xw.ch, src_w = cols*xw.cw, src_h = rows*xw.ch; | ||
1798 | int dst_x = BORDER+src_x, dst_y = BORDER+src_y; | ||
1799 | XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, src_x, src_y, src_w, src_h, dst_x, dst_y); | ||
1800 | } | ||
1801 | |||
1789 | void | 1802 | void |
1790 | xdrawcursor(void) { | 1803 | xdrawcursor(void) { |
1791 | static int oldx = 0; | 1804 | static int oldx = 0; |
@@ -1805,7 +1818,9 @@ xdrawcursor(void) { | |||
1805 | xdraws(term.line[oldy][oldx].c, term.line[oldy][oldx], oldx, oldy, 1, sl); | 1818 | xdraws(term.line[oldy][oldx].c, term.line[oldy][oldx], oldx, oldy, 1, sl); |
1806 | } else | 1819 | } else |
1807 | xclear(oldx, oldy, oldx, oldy); | 1820 | xclear(oldx, oldy, oldx, oldy); |
1808 | 1821 | ||
1822 | xcopy(oldx, oldy, 1, 1); | ||
1823 | |||
1809 | /* draw the new one */ | 1824 | /* draw the new one */ |
1810 | if(!(term.c.state & CURSOR_HIDE) && (xw.state & WIN_FOCUSED)) { | 1825 | if(!(term.c.state & CURSOR_HIDE) && (xw.state & WIN_FOCUSED)) { |
1811 | sl = utf8size(g.c); | 1826 | sl = utf8size(g.c); |
@@ -1814,11 +1829,14 @@ xdrawcursor(void) { | |||
1814 | xdraws(g.c, g, term.c.x, term.c.y, 1, sl); | 1829 | xdraws(g.c, g, term.c.x, term.c.y, 1, sl); |
1815 | oldx = term.c.x, oldy = term.c.y; | 1830 | oldx = term.c.x, oldy = term.c.y; |
1816 | } | 1831 | } |
1832 | |||
1833 | xcopy(term.c.x, term.c.y, 1, 1); | ||
1817 | } | 1834 | } |
1818 | 1835 | ||
1819 | void | 1836 | void |
1820 | draw() { | 1837 | draw() { |
1821 | drawregion(0, 0, term.col, term.row); | 1838 | drawregion(0, 0, term.col, term.row); |
1839 | gettimeofday(&xw.lastdraw, NULL); | ||
1822 | } | 1840 | } |
1823 | 1841 | ||
1824 | void | 1842 | void |
@@ -1859,9 +1877,9 @@ drawregion(int x1, int y1, int x2, int y2) { | |||
1859 | } | 1877 | } |
1860 | if(ib > 0) | 1878 | if(ib > 0) |
1861 | xdraws(buf, base, ox, y, ic, ib); | 1879 | xdraws(buf, base, ox, y, ic, ib); |
1880 | xcopy(0, y, term.col, 1); | ||
1862 | } | 1881 | } |
1863 | xdrawcursor(); | 1882 | xdrawcursor(); |
1864 | XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, x1*xw.cw, y1*xw.ch, x2*xw.cw, y2*xw.ch, BORDER, BORDER); | ||
1865 | } | 1883 | } |
1866 | 1884 | ||
1867 | void | 1885 | void |
@@ -2006,25 +2024,42 @@ resize(XEvent *e) { | |||
2006 | xresize(col, row); | 2024 | xresize(col, row); |
2007 | } | 2025 | } |
2008 | 2026 | ||
2027 | int | ||
2028 | last_draw_too_old(void) { | ||
2029 | struct timeval now; | ||
2030 | gettimeofday(&now, NULL); | ||
2031 | return TIMEDIFF(now, xw.lastdraw) >= PRINT_TIMEOUT/1000; | ||
2032 | } | ||
2033 | |||
2009 | void | 2034 | void |
2010 | run(void) { | 2035 | run(void) { |
2011 | XEvent ev; | 2036 | XEvent ev; |
2012 | fd_set rfd; | 2037 | fd_set rfd; |
2013 | int xfd = XConnectionNumber(xw.dpy); | 2038 | int xfd = XConnectionNumber(xw.dpy); |
2014 | 2039 | struct timeval timeout = {0}; | |
2040 | int stuff_to_print = 0; | ||
2041 | |||
2015 | for(;;) { | 2042 | for(;;) { |
2016 | FD_ZERO(&rfd); | 2043 | FD_ZERO(&rfd); |
2017 | FD_SET(cmdfd, &rfd); | 2044 | FD_SET(cmdfd, &rfd); |
2018 | FD_SET(xfd, &rfd); | 2045 | FD_SET(xfd, &rfd); |
2019 | if(select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, NULL) < 0) { | 2046 | timeout.tv_sec = 0; |
2047 | timeout.tv_usec = SELECT_TIMEOUT; | ||
2048 | if(select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, &timeout) < 0) { | ||
2020 | if(errno == EINTR) | 2049 | if(errno == EINTR) |
2021 | continue; | 2050 | continue; |
2022 | die("select failed: %s\n", SERRNO); | 2051 | die("select failed: %s\n", SERRNO); |
2023 | } | 2052 | } |
2024 | if(FD_ISSET(cmdfd, &rfd)) { | 2053 | if(FD_ISSET(cmdfd, &rfd)) { |
2025 | ttyread(); | 2054 | ttyread(); |
2055 | stuff_to_print = 1; | ||
2056 | } | ||
2057 | |||
2058 | if(stuff_to_print && last_draw_too_old()) { | ||
2059 | stuff_to_print = 0; | ||
2026 | draw(); | 2060 | draw(); |
2027 | } | 2061 | } |
2062 | |||
2028 | while(XPending(xw.dpy)) { | 2063 | while(XPending(xw.dpy)) { |
2029 | XNextEvent(xw.dpy, &ev); | 2064 | XNextEvent(xw.dpy, &ev); |
2030 | if(XFilterEvent(&ev, xw.win)) | 2065 | if(XFilterEvent(&ev, xw.win)) |
@@ -2050,7 +2085,7 @@ main(int argc, char *argv[]) { | |||
2050 | case 'w': | 2085 | case 'w': |
2051 | if(++i < argc) opt_embed = argv[i]; | 2086 | if(++i < argc) opt_embed = argv[i]; |
2052 | break; | 2087 | break; |
2053 | case 'e': | 2088 | case 'e': |
2054 | /* eat every remaining arguments */ | 2089 | /* eat every remaining arguments */ |
2055 | if(++i < argc) opt_cmd = &argv[i]; | 2090 | if(++i < argc) opt_cmd = &argv[i]; |
2056 | goto run; | 2091 | goto run; |