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

Reply via email to