slightly reorganize libmemdraw to allow for allocators other than the pool library. this also drags in some of russ' fixes to the drawing routines. Reference: /n/patches.lsub.org/patch/memdrawalloc Date: Sat Sep 15 20:14:24 CES 2012 Signed-off-by: quanstro@quanstro.net --- /sys/src/libmemdraw/alloc.c Thu Apr 12 12:26:21 2012 +++ /sys/src/libmemdraw/alloc.c Sun Sep 9 03:04:42 2012 @@ -4,7 +4,9 @@ #include #include -void +extern Pool* imagmem; + +/* static */ void memimagemove(void *from, void *to) { Memdata *md; @@ -20,6 +22,13 @@ md->bdata = (uchar*)md->base+sizeof(Memdata*)+sizeof(ulong); } +void +memdrawallocinit(void) +{ + if(strcmp(imagmem->name, "Image") == 0 || strcmp(imagmem->name, "image") == 0) + imagmem->move = memimagemove; +} + Memimage* allocmemimaged(Rectangle r, ulong chan, Memdata *md) { @@ -122,80 +131,4 @@ free(i->data); } free(i); -} - -/* - * Wordaddr is deprecated. - */ -ulong* -wordaddr(Memimage *i, Point p) -{ - return (ulong*) ((uintptr)byteaddr(i, p) & ~(sizeof(ulong)-1)); -} - -uchar* -byteaddr(Memimage *i, Point p) -{ - uchar *a; - - a = i->data->bdata+i->zero+sizeof(ulong)*p.y*i->width; - - if(i->depth < 8){ - /* - * We need to always round down, - * but C rounds toward zero. - */ - int np; - np = 8/i->depth; - if(p.x < 0) - return a+(p.x-np+1)/np; - else - return a+p.x/np; - } - else - return a+p.x*(i->depth/8); -} - -int -memsetchan(Memimage *i, ulong chan) -{ - int d; - int t, j, k; - ulong cc; - int bytes; - - if((d = chantodepth(chan)) == 0) { - werrstr("bad channel descriptor"); - return -1; - } - - i->depth = d; - i->chan = chan; - i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes); - bytes = 1; - for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){ - t=TYPE(cc); - if(t < 0 || t >= NChan){ - werrstr("bad channel string"); - return -1; - } - if(t == CGrey) - i->flags |= Fgrey; - if(t == CAlpha) - i->flags |= Falpha; - if(t == CMap && i->cmap == nil){ - i->cmap = memdefcmap; - i->flags |= Fcmap; - } - - i->shift[t] = j; - i->mask[t] = (1<nbits[t] = NBITS(cc); - if(NBITS(cc) != 8) - bytes = 0; - } - i->nchan = k; - if(bytes) - i->flags |= Fbytes; - return 0; } --- /sys/src/libmemdraw/mkfile Thu Apr 12 12:26:21 2012 +++ /sys/src/libmemdraw/mkfile Sun Sep 9 02:53:35 2012 @@ -3,6 +3,7 @@ LIB=/$objtype/lib/libmemdraw.a OFILES=\ alloc.$O\ + addr.$O\ arc.$O\ cload.$O\ cmap.$O\ @@ -15,6 +16,7 @@ iprint.$O\ line.$O\ load.$O\ + memsetchan.$O\ openmemsubfont.$O\ poly.$O\ read.$O\ --- /sys/src/libmemdraw/memsetchan.c Thu Jan 1 00:00:00 1970 +++ /sys/src/libmemdraw/memsetchan.c Sun Sep 9 02:53:36 2012 @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +int +memsetchan(Memimage *i, ulong chan) +{ + int d; + int t, j, k; + ulong cc; + int bytes; + + if((d = chantodepth(chan)) == 0) { + werrstr("bad channel descriptor"); + return -1; + } + + i->depth = d; + i->chan = chan; + i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes); + bytes = 1; + for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){ + t=TYPE(cc); + if(t < 0 || t >= NChan){ + werrstr("bad channel string"); + return -1; + } + if(t == CGrey) + i->flags |= Fgrey; + if(t == CAlpha) + i->flags |= Falpha; + if(t == CMap && i->cmap == nil){ + i->cmap = memdefcmap; + i->flags |= Fcmap; + } + + i->shift[t] = j; + i->mask[t] = (1<nbits[t] = NBITS(cc); + if(NBITS(cc) != 8) + bytes = 0; + } + i->nchan = k; + if(bytes) + i->flags |= Fbytes; + return 0; +} --- /sys/src/libmemdraw/addr.c Thu Jan 1 00:00:00 1970 +++ /sys/src/libmemdraw/addr.c Sun Sep 9 02:53:33 2012 @@ -0,0 +1,37 @@ +#include +#include +#include +#include + +/* + * Wordaddr is deprecated. + */ +ulong* +wordaddr(Memimage *i, Point p) +{ + return (ulong*) ((uintptr)byteaddr(i, p) & ~(sizeof(ulong)-1)); +} + +uchar* +byteaddr(Memimage *i, Point p) +{ + uchar *a; + + a = i->data->bdata+i->zero+sizeof(ulong)*p.y*i->width; + + if(i->depth < 8){ + /* + * We need to always round down, + * but C rounds toward zero. + */ + int np; + np = 8/i->depth; + if(p.x < 0) + return a+(p.x-np+1)/np; + else + return a+p.x/np; + } + else + return a+p.x*(i->depth/8); +} + --- /sys/src/libmemdraw/draw.c Thu Apr 12 12:26:21 2012 +++ /sys/src/libmemdraw/draw.c Thu Sep 13 22:51:56 2012 @@ -2,32 +2,41 @@ #include #include #include -#include -extern Pool* imagmem; int drawdebug; -static int tablesbuilt; /* perfect approximation to NTSC = .299r+.587g+.114b when 0 ≤ r,g,b < 256 */ #define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19) /* - * for 0 ≤ x ≤ 255*255, (x*0x0101+0x100)>>16 is a perfect approximation. - * for 0 ≤ x < (1<<16), x/255 = ((x+1)*0x0101)>>16 is a perfect approximation. - * the last one is perfect for all up to 1<<16, avoids a multiply, but requires a rathole. + * For 16-bit values, x / 255 == (t = x+1, (t+(t>>8)) >> 8). + * We add another 127 to round to the nearest value rather + * than truncate. + * + * CALCxy does x bytewise calculations on y input images (x=1,4; y=1,2). + * CALC2x does two parallel 16-bit calculations on y input images (y=1,2). */ -/* #define DIV255(x) (((x)*257+256)>>16) */ -#define DIV255(x) ((((x)+1)*257)>>16) -/* #define DIV255(x) (tmp=(x)+1, (tmp+(tmp>>8))>>8) */ - -#define MUL(x, y, t) (t = (x)*(y)+128, (t+(t>>8))>>8) -#define MASK13 0xFF00FF00 -#define MASK02 0x00FF00FF -#define MUL13(a, x, t) (t = (a)*(((x)&MASK13)>>8)+128, ((t+((t>>8)&MASK02))>>8)&MASK02) -#define MUL02(a, x, t) (t = (a)*(((x)&MASK02)>>0)+128, ((t+((t>>8)&MASK02))>>8)&MASK02) -#define MUL0123(a, x, s, t) ((MUL13(a, x, s)<<8)|MUL02(a, x, t)) +#define CALC11(a, v, tmp) \ + (tmp=(a)*(v)+128, (tmp+(tmp>>8))>>8) + +#define CALC12(a1, v1, a2, v2, tmp) \ + (tmp=(a1)*(v1)+(a2)*(v2)+128, (tmp+(tmp>>8))>>8) + +#define MASK 0xFF00FF + +#define CALC21(a, vvuu, tmp) \ + (tmp=(a)*(vvuu)+0x00800080, ((tmp+((tmp>>8)&MASK))>>8)&MASK) + +#define CALC41(a, rgba, tmp1, tmp2) \ + (CALC21(a, rgba & MASK, tmp1) | \ + (CALC21(a, (rgba>>8)&MASK, tmp2)<<8)) -#define MUL2(u, v, x, y) (t = (u)*(v)+(x)*(y)+256, (t+(t>>8))>>8) +#define CALC22(a1, vvuu1, a2, vvuu2, tmp) \ + (tmp=(a1)*(vvuu1)+(a2)*(vvuu2)+0x00800080, ((tmp+((tmp>>8)&MASK))>>8)&MASK) + +#define CALC42(a1, rgba1, a2, rgba2, tmp1, tmp2) \ + (CALC22(a1, rgba1 & MASK, a2, rgba2 & MASK, tmp1) | \ + (CALC22(a1, (rgba1>>8) & MASK, a2, (rgba2>>8) & MASK, tmp2)<<8)) static void mktables(void); typedef int Subdraw(Memdrawparam*); @@ -40,11 +49,10 @@ Memimage *memtransparent; Memimage *memopaque; -int _ifmt(Fmt*); - void memimageinit(void) { + extern void memdrawallocinit(void); static int didinit = 0; if(didinit) @@ -52,15 +60,13 @@ didinit = 1; - if(strcmp(imagmem->name, "Image") == 0 || strcmp(imagmem->name, "image") == 0) - imagmem->move = memimagemove; + memdrawallocinit(); mktables(); _memmkcmap(); fmtinstall('R', Rfmt); fmtinstall('P', Pfmt); - fmtinstall('b', _ifmt); memones = allocmemimage(Rect(0,0,1,1), GREY1); memones->flags |= Frepl; @@ -342,13 +348,6 @@ { int i, j, mask, sh, small; - if(tablesbuilt) - return; - - fmtinstall('R', Rfmt); - fmtinstall('P', Pfmt); - tablesbuilt = 1; - /* bit replication up to 8 bits */ for(i=0; i<256; i++){ for(j=0; j<=8; j++){ /* j <= 8 [sic] */ @@ -803,41 +802,85 @@ return bdst; } +/* + * Do the channels in the buffers match enough + * that we can do word-at-a-time operations + * on the pixels? + */ +static int +chanmatch(Buffer *bdst, Buffer *bsrc) +{ + uchar *drgb, *srgb; + + /* + * first, r, g, b must be in the same place + * in the rgba word. + */ + drgb = (uchar*)bdst->rgba; + srgb = (uchar*)bsrc->rgba; + if(bdst->red - drgb != bsrc->red - srgb + || bdst->blu - drgb != bsrc->blu - srgb + || bdst->grn - drgb != bsrc->grn - srgb) + return 0; + + /* + * that implies alpha is in the same place, + * if it is there at all (it might be == &ones). + * if the destination is &ones, we can scribble + * over the rgba slot just fine. + */ + if(bdst->alpha == &ones) + return 1; + + /* + * if the destination is not ones but the src is, + * then the simultaneous calculation will use + * bogus bytes from the src's rgba. no good. + */ + if(bsrc->alpha == &ones) + return 0; + + /* + * otherwise, alphas are in the same place. + */ + return 1; +} + static Buffer alphacalc14(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op) { Buffer obdst; int fd, sadelta; int i, sa, ma, q; - ulong s, t; + ulong t, t1; obdst = bdst; sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta; - q = bsrc.delta == 4 && bdst.delta == 4; + q = bsrc.delta == 4 && bdst.delta == 4 && chanmatch(&bdst, &bsrc); for(i=0; i