ref: c923daa68daae862ccdd638cbb9e255c609b09de
parent: 0b8bc0b02656311de2b1542d5819d7118c789ab5
author: qwx <qwx@sciops.net>
date: Tue Jul 25 04:47:45 EDT 2023
haha draw go brrr performance improvements and regression fixes - get rid of secondary backing store - limit drawproc updates to a given interval - don't redraw entire image on update, erase and redraw markers and stats - update view if changes occur while paused makes code yet more complicated, but the latency was horrible; ui is slowed down by the scheduling between athread and alt(); it makes little sense at this point, should replace athread with an actual proc however inconvenient it might be, then micing will not feel like swimming through larch vomit
--- a/dat.h
+++ b/dat.h
@@ -34,7 +34,7 @@
extern QLock lsync;
extern int stereo;
-extern int debug;
+extern int debug, paused;
extern int debugdraw;
#define MIN(x,y) ((x) < (y) ? (x) : (y))
--- a/draw.c
+++ b/draw.c
@@ -19,9 +19,8 @@
Ncol,
};
static Image *col[Ncol];
-static Image *viewbg, *view;
-static Rectangle liner;
-static Point statp;
+static Image *view;
+static Rectangle liner, statr;
static usize views, viewe, viewmax;
static int bgscalyl, bgscalyr;
static double bgscalf;
@@ -75,10 +74,10 @@
if(pos <= views || pos >= viewe)
return 0;
- r = view->r;
+ r = screen->r;
r.min.x += (pos - views) / T;
r.max.x = r.min.x + 1;
- draw(view, r, c, nil, ZP);
+ draw(screen, r, c, nil, subpt(r.min, screen->r.min));
return 1;
}
@@ -99,29 +98,38 @@
static void
drawsamps(void*)
{
- int x, lmin, lmax, rmin, rmax;
- usize n, m, k;
+ int ox, n, lmin, lmax, rmin, rmax;
+ usize m, k;
s16int s;
+ double x;
uchar *p, *e;
Rectangle l, r;
+ Point range;
Dot d;
for(;;){
end:
- recvul(drawc);
+ if(recv(drawc, &range) < 0)
+ break;
again:
+ r = view->r;
+ r.min.x = (range.x - views) / T;
+ r.max.x = (range.y - views) / T;
lockdisplay(display);
- draw(viewbg, viewbg->r, col[Cbg], nil, ZP);
+ draw(view, r, col[Cbg], nil, ZP);
unlockdisplay(display);
d = *current;
- d.from = 0;
- d.cur = views;
- d.to = d.totalsz;
- m = viewe - views;
- x = 0;
+ d.from = range.x;
+ d.cur = d.from;
+ d.to = range.y;
+ m = d.to - d.from;
+ ox = 0;
+ x = 0.0;
qlock(&lsync);
while(m > 0){
- if(nbrecvul(drawc) == 1){
+ if((n = nbrecv(drawc, &range)) < 0)
+ return;
+ else if(n == 1){
qunlock(&lsync);
goto again;
}
@@ -156,18 +164,21 @@
}
l = Rect(x, bgscalyl - lmax / bgscalf,
x+sampwidth, bgscalyl - lmin / bgscalf);
- r = Rect(x, bgscalyr - rmax / bgscalf,
- x+sampwidth, bgscalyr - rmin / bgscalf);
lockdisplay(display);
- draw(viewbg, l, col[Csamp], nil, ZP);
- if(stereo)
- draw(viewbg, r, col[Csamp], nil, ZP);
+ draw(view, l, col[Csamp], nil, ZP);
+ if(stereo){
+ r = Rect(x, bgscalyr - rmax / bgscalf,
+ x+sampwidth, bgscalyr - rmin / bgscalf);
+ draw(view, r, col[Csamp], nil, ZP);
+ }
unlockdisplay(display);
- x = (d.cur - views) / T;
- if(x % 320 == 0)
- update();
+ if(x - ox >= 1600){
+ update(ox, x);
+ ox = x;
+ }
+ x += k / T;
}
- update();
+ update(ox, Dx(screen->r));
qunlock(&lsync);
}
}
@@ -178,8 +189,9 @@
char s[256];
Point p;
+ draw(screen, statr, col[Cbg], nil, ZP);
seprint(s, s+sizeof s, "T %zd @ %τ", T / Sampsz, current->cur);
- p = string(screen, statp, col[Ctext], ZP, font, s);
+ p = string(screen, statr.min, col[Ctext], ZP, font, s);
if(current->from > 0 || current->to < current->totalsz){
seprint(s, s+sizeof s, " ↺ %τ - %τ", current->from, current->to);
p = string(screen, p, col[Cloop], ZP, font, s);
@@ -188,12 +200,12 @@
seprint(s, s+sizeof s, " ‡ %τ", current->off);
p = string(screen, p, col[Cins], ZP, font, s);
}
+ statr.max.x = p.x;
}
static void
-drawview(void)
+drawmarks(void)
{
- draw(view, view->r, viewbg, nil, ZP);
if(debugdraw)
drawchunks();
drawpos(current->from, col[Cloop]);
@@ -203,20 +215,22 @@
}
void
-update(void)
+update(int x, int x´)
{
- int x;
- usize p;
+ Rectangle r;
- p = current->cur;
+ r = liner;
lockdisplay(display);
- drawview();
- draw(screen, screen->r, view, nil, ZP);
- x = screen->r.min.x + (p - views) / T;
- liner.min.x = x;
- liner.max.x = x + 1;
- if(p >= views)
- draw(screen, liner, col[Cline], nil, ZP);
+ draw(screen, liner, view, nil, subpt(r.min, screen->r.min));
+ if(x < x´){
+ r.min.x = screen->r.min.x + x;
+ r.max.x = screen->r.min.x + x´;
+ draw(screen, r, view, nil, subpt(r.min, screen->r.min));
+ }
+ liner.min.x = screen->r.min.x + (current->cur - views) / T;
+ liner.max.x = liner.min.x + 1;
+ drawpos(current->cur, col[Cline]);
+ drawmarks();
drawstat();
flushimage(display, 1);
unlockdisplay(display);
@@ -290,6 +304,10 @@
{
assert((from & 3) == 0);
assert((to & 3) == 0);
+ if(current->from > views)
+ drawpos(current->from, view);
+ if(current->to < viewe)
+ drawpos(current->to, view);
current->from = from;
current->to = to;
if(current->cur < from || current->cur >= to)
@@ -305,7 +323,8 @@
return -1;
}
current->off = current->cur = off;
- update();
+ if(paused)
+ update(0, 0);
return 0;
}
@@ -320,7 +339,8 @@
setrange(off, current->to);
else
setrange(current->from, off);
- update();
+ if(paused)
+ update(0, 0);
}
void
@@ -343,14 +363,12 @@
x = screen->r.min.x + (current->cur - views) / T;
viewr = rectsubpt(screen->r, screen->r.min);
- statp = screen->r.min;
+ statr = screen->r;
if(stereo)
- statp.y += (Dy(screen->r) - font->height) / 2 + 1;
+ statr.min.y += (Dy(screen->r) - font->height) / 2 + 1;
else
- statp.y = screen->r.max.y - font->height;
- freeimage(viewbg);
+ statr.min.y = screen->r.max.y - font->height;
freeimage(view);
- viewbg = eallocimage(viewr, 0, DNofill);
view = eallocimage(viewr, 0, DNofill);
liner = screen->r;
liner.min.x = x;
@@ -364,6 +382,7 @@
redraw(int all)
{
usize span;
+ Point p;
lockdisplay(display);
T = (vlong)(current->totalsz / zoom / Dx(screen->r)) & ~3;
@@ -377,7 +396,8 @@
if(all)
resetdraw();
unlockdisplay(display);
- nbsendul(drawc, 1);
+ p = Pt(views, viewe);
+ nbsend(drawc, &p);
}
void
@@ -404,7 +424,7 @@
col[Cloop] = eallocimage(Rect(0,0,1,1), 1, 0x8888CCFF);
col[Cchunk] = eallocimage(Rect(0,0,1,1), 1, 0xEE0000FF);
}
- if((drawc = chancreate(sizeof(ulong), 4)) == nil)
+ if((drawc = chancreate(sizeof(Point), 4)) == nil)
sysfatal("chancreate: %r");
if(proccreate(drawsamps, nil, mainstacksize) < 0)
sysfatal("proccreate: %r");
--- a/fns.h
+++ b/fns.h
@@ -10,7 +10,7 @@
Chunk* loadfile(int, Dot*);
int cmd(char*);
int initcmd(int);
-void update(void);
+void update(int, int);
void setzoom(int, int);
int zoominto(vlong, vlong);
void setrange(usize, usize);
--- a/pplay.c
+++ b/pplay.c
@@ -10,7 +10,7 @@
extern QLock lsync;
int stereo;
-int debug;
+int debug, paused = 1;
static Keyboardctl *kc;
static Mousectl *mc;
@@ -42,7 +42,7 @@
threadexits("write");
}
nerr = 0;
- update();
+ update(0, 0);
skip:
yield();
}
@@ -51,20 +51,18 @@
static void
toggleplay(void)
{
- static int play;
-
- if(play ^= 1){
+ if(paused ^= 1){
+ if(!cat)
+ close(afd);
+ afd = -1;
+ }else{
if((afd = cat ? 1 : open("/dev/audio", OWRITE)) < 0){
fprint(2, "toggleplay: %r\n");
- play = 0;
+ paused ^= 1;
return;
}
if(threadcreate(athread, nil, 2*mainstacksize) < 0)
sysfatal("threadcreate: %r");
- }else{
- if(!cat)
- close(afd);
- afd = -1;
}
}
@@ -155,7 +153,7 @@
case 'S': stereo ^= 1; redraw(1); break;
case ' ': toggleplay(); break;
case 'b': setjump(current->from); break;
- case Kesc: setrange(0, current->totalsz); update(); break;
+ case Kesc: setrange(0, current->totalsz); update(0, 0); break;
case '\n': zoominto(current->from, current->to); break;
case 'z': zoominto(0, current->totalsz); break;
case '-': setzoom(-1, 0); break;
@@ -173,8 +171,8 @@
}
qlock(&lsync);
switch(cmd(p)){
- case -1: fprint(2, "cmd \"%s\" failed: %r\n", p); update(); break;
- case 0: update(); break;
+ case -1: fprint(2, "cmd \"%s\" failed: %r\n", p); update(0, 0); break;
+ case 0: update(0, 0); break;
case 1: redraw(0); break;
case 2: redraw(1); break;
}