FYI I've applied this patch to st's default branch (commit #245) Enjoy, -brandon
Brandon Invergo <bran...@invergo.net> writes: > Hi, > As some background, I've been using st on an Arm device (Genesi Efika > MX) which has relatively low specs compared to your average x86/amd64 > computer. st should be ideal because of how small it is compared to > xterm or rxvt but the reality is that its rendering is quite a bit > slower. Under heavy processor load, such as building a package, I can > literally watch the terminal window refreshing (ie I can see a line > traveling down the window, above which the window is refreshed and below > which the window is dirty...."tearing"). > > I've changed the code to use the X Double Buffer Extension (Xdbe). > Instead of rendering to a Pixbuf and then copying that Pixbuf to the > window, which is a relatively slow operation, it now renders to an > XdbeBackBuffer and then simply swaps buffers with the window. The result > is tear-free and apparently faster rendering even on an 800mhz Arm cpu. > > A side effect is that the code is a bit shorter as a result too. For > example, xresize() does almost nothing now, since the XdbeBackBuffer is > automatically resized with the window (see the DBE manpage), so several > Xlib calls can be removed from that function. > > The provided diff is against the default branch, however I also got it > working for the xft branch. I can provide a diff for that too if you > want but the only extra difference is that any Xft draw-related calls > should work on xw.buf rather than xw.win (including the one in > xresize()). > > LIBS in config.mk should have -lXext appended. I forgot to include that > in the patch. > > A few caveats: 1) my C skills are a bit rusty, 2) I'm unfamiliar with > Mercurial, 3) I'm completely new to Xlib. So, while it Works For Me > (tm), you might want to test it a bit and let me know if I messed up > something. > > I'm going to keep hacking on it to try to improve further the speed if I > can. > > Cheers, > Brandon Invergo > diff -r e1414acbe547 st.c > --- a/st.c Mon Feb 27 12:48:13 2012 +0100 > +++ b/st.c Fri Apr 20 09:10:28 2012 +0200 > @@ -24,6 +24,7 @@ > #include <X11/Xutil.h> > #include <X11/cursorfont.h> > #include <X11/keysym.h> > +#include <X11/extensions/Xdbe.h> > > #if defined(__linux) > #include <pty.h> > @@ -178,7 +179,7 @@ > Display* dpy; > Colormap cmap; > Window win; > - Pixmap buf; > + XdbeBackBuffer buf; > Atom xembed; > XIM xim; > XIC xic; > @@ -270,7 +271,7 @@ > static void xdraws(char *, Glyph, int, int, int, int); > static void xhints(void); > static void xclear(int, int, int, int); > -static void xcopy(int, int, int, int); > +static void xcopy(); > static void xdrawcursor(void); > static void xinit(void); > static void xloadcols(void); > @@ -1620,32 +1621,8 @@ > > void > xresize(int col, int row) { > - Pixmap newbuf; > - int oldw, oldh; > - > - oldw = xw.bufw; > - oldh = xw.bufh; > xw.bufw = MAX(1, col * xw.cw); > xw.bufh = MAX(1, row * xw.ch); > - newbuf = XCreatePixmap(xw.dpy, xw.win, xw.bufw, xw.bufh, > XDefaultDepth(xw.dpy, xw.scr)); > - XCopyArea(xw.dpy, xw.buf, newbuf, dc.gc, 0, 0, xw.bufw, xw.bufh, 0, 0); > - XFreePixmap(xw.dpy, xw.buf); > - XSetForeground(xw.dpy, dc.gc, dc.col[DefaultBG]); > - if(xw.bufw > oldw) > - XFillRectangle(xw.dpy, newbuf, dc.gc, oldw, 0, > - xw.bufw-oldw, MIN(xw.bufh, oldh)); > - else if(xw.bufw < oldw && (BORDER > 0 || xw.w > xw.bufw)) > - XClearArea(xw.dpy, xw.win, BORDER+xw.bufw, BORDER, > - xw.w-xw.bufh-BORDER, BORDER+MIN(xw.bufh, oldh), > - False); > - if(xw.bufh > oldh) > - XFillRectangle(xw.dpy, newbuf, dc.gc, 0, oldh, > - xw.bufw, xw.bufh-oldh); > - else if(xw.bufh < oldh && (BORDER > 0 || xw.h > xw.bufh)) > - XClearArea(xw.dpy, xw.win, BORDER, BORDER+xw.bufh, > - xw.w-2*BORDER, xw.h-xw.bufh-BORDER, > - False); > - xw.buf = newbuf; > } > > void > @@ -1801,7 +1778,7 @@ > CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask > | CWColormap, > &attrs); > - xw.buf = XCreatePixmap(xw.dpy, xw.win, xw.bufw, xw.bufh, > XDefaultDepth(xw.dpy, xw.scr)); > + xw.buf = XdbeAllocateBackBufferName(xw.dpy, xw.win, XdbeCopied); > > > /* input methods */ > @@ -1871,10 +1848,10 @@ > > /* copy buffer pixmap to screen pixmap */ > void > -xcopy(int x, int y, int cols, int rows) { > - int src_x = x*xw.cw, src_y = y*xw.ch, src_w = cols*xw.cw, src_h = > rows*xw.ch; > - int dst_x = BORDER+src_x, dst_y = BORDER+src_y; > - XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, src_x, src_y, src_w, src_h, > dst_x, dst_y); > +xcopy() { > + XdbeSwapInfo swpinfo[1] = {{xw.win, XdbeCopied}}; > + XdbeSwapBuffers(xw.dpy, swpinfo, 1); > + > } > > void > @@ -1918,6 +1895,7 @@ > void > draw() { > drawregion(0, 0, term.col, term.row); > + xcopy(); > gettimeofday(&xw.lastdraw, NULL); > } > > @@ -1959,7 +1937,6 @@ > } > if(ib > 0) > xdraws(buf, base, ox, y, ic, ib); > - xcopy(0, y, term.col, 1); > } > xdrawcursor(); > } > @@ -1968,13 +1945,10 @@ > expose(XEvent *ev) { > XExposeEvent *e = &ev->xexpose; > if(xw.state & WIN_REDRAW) { > - if(!e->count) { > + if(!e->count) > xw.state &= ~WIN_REDRAW; > - xcopy(0, 0, term.col, term.row); > - } > - } else > - XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, e->x-BORDER, > e->y-BORDER, > - e->width, e->height, e->x, e->y); > + } > + xcopy(); > } > > void