17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <memdraw.h>
57dd7cddfSDavid du Colombier #include <pool.h>
67dd7cddfSDavid du Colombier
77dd7cddfSDavid du Colombier void
memimagemove(void * from,void * to)87dd7cddfSDavid du Colombier memimagemove(void *from, void *to)
97dd7cddfSDavid du Colombier {
107dd7cddfSDavid du Colombier Memdata *md;
117dd7cddfSDavid du Colombier
127dd7cddfSDavid du Colombier md = *(Memdata**)to;
137dd7cddfSDavid du Colombier if(md->base != from){
147dd7cddfSDavid du Colombier print("compacted data not right: #%p\n", md->base);
157dd7cddfSDavid du Colombier abort();
167dd7cddfSDavid du Colombier }
177dd7cddfSDavid du Colombier md->base = to;
187dd7cddfSDavid du Colombier
197dd7cddfSDavid du Colombier /* if allocmemimage changes this must change too */
2090e65e0fSDavid du Colombier md->bdata = (uchar*)md->base+sizeof(Memdata*)+sizeof(ulong);
217dd7cddfSDavid du Colombier }
227dd7cddfSDavid du Colombier
237dd7cddfSDavid du Colombier Memimage*
allocmemimaged(Rectangle r,ulong chan,Memdata * md)247dd7cddfSDavid du Colombier allocmemimaged(Rectangle r, ulong chan, Memdata *md)
257dd7cddfSDavid du Colombier {
267dd7cddfSDavid du Colombier int d;
277dd7cddfSDavid du Colombier ulong l;
287dd7cddfSDavid du Colombier Memimage *i;
297dd7cddfSDavid du Colombier
30d3c05884SDavid du Colombier if(Dx(r) <= 0 || Dy(r) <= 0){
31d3c05884SDavid du Colombier werrstr("bad rectangle %R", r);
32d3c05884SDavid du Colombier return nil;
33d3c05884SDavid du Colombier }
347dd7cddfSDavid du Colombier if((d = chantodepth(chan)) == 0) {
357dd7cddfSDavid du Colombier werrstr("bad channel descriptor %.8lux", chan);
367dd7cddfSDavid du Colombier return nil;
377dd7cddfSDavid du Colombier }
387dd7cddfSDavid du Colombier
397dd7cddfSDavid du Colombier l = wordsperline(r, d);
407dd7cddfSDavid du Colombier
417dd7cddfSDavid du Colombier i = mallocz(sizeof(Memimage), 1);
427dd7cddfSDavid du Colombier if(i == nil)
437dd7cddfSDavid du Colombier return nil;
447dd7cddfSDavid du Colombier
457dd7cddfSDavid du Colombier i->data = md;
467dd7cddfSDavid du Colombier i->zero = sizeof(ulong)*l*r.min.y;
477dd7cddfSDavid du Colombier
487dd7cddfSDavid du Colombier if(r.min.x >= 0)
497dd7cddfSDavid du Colombier i->zero += (r.min.x*d)/8;
507dd7cddfSDavid du Colombier else
517dd7cddfSDavid du Colombier i->zero -= (-r.min.x*d+7)/8;
527dd7cddfSDavid du Colombier i->zero = -i->zero;
537dd7cddfSDavid du Colombier i->width = l;
547dd7cddfSDavid du Colombier i->r = r;
557dd7cddfSDavid du Colombier i->clipr = r;
567dd7cddfSDavid du Colombier i->flags = 0;
577dd7cddfSDavid du Colombier i->layer = nil;
587dd7cddfSDavid du Colombier i->cmap = memdefcmap;
597dd7cddfSDavid du Colombier if(memsetchan(i, chan) < 0){
607dd7cddfSDavid du Colombier free(i);
617dd7cddfSDavid du Colombier return nil;
627dd7cddfSDavid du Colombier }
637dd7cddfSDavid du Colombier return i;
647dd7cddfSDavid du Colombier }
657dd7cddfSDavid du Colombier
667dd7cddfSDavid du Colombier Memimage*
allocmemimage(Rectangle r,ulong chan)677dd7cddfSDavid du Colombier allocmemimage(Rectangle r, ulong chan)
687dd7cddfSDavid du Colombier {
697dd7cddfSDavid du Colombier int d;
7090e65e0fSDavid du Colombier uchar *p;
717dd7cddfSDavid du Colombier ulong l, nw;
727dd7cddfSDavid du Colombier Memdata *md;
737dd7cddfSDavid du Colombier Memimage *i;
747dd7cddfSDavid du Colombier
757dd7cddfSDavid du Colombier if((d = chantodepth(chan)) == 0) {
767dd7cddfSDavid du Colombier werrstr("bad channel descriptor %.8lux", chan);
777dd7cddfSDavid du Colombier return nil;
787dd7cddfSDavid du Colombier }
797dd7cddfSDavid du Colombier
807dd7cddfSDavid du Colombier l = wordsperline(r, d);
817dd7cddfSDavid du Colombier nw = l*Dy(r);
827dd7cddfSDavid du Colombier md = malloc(sizeof(Memdata));
837dd7cddfSDavid du Colombier if(md == nil)
847dd7cddfSDavid du Colombier return nil;
857dd7cddfSDavid du Colombier
867dd7cddfSDavid du Colombier md->ref = 1;
8790e65e0fSDavid du Colombier md->base = poolalloc(imagmem, sizeof(Memdata*)+(1+nw)*sizeof(ulong));
887dd7cddfSDavid du Colombier if(md->base == nil){
897dd7cddfSDavid du Colombier free(md);
907dd7cddfSDavid du Colombier return nil;
917dd7cddfSDavid du Colombier }
927dd7cddfSDavid du Colombier
9390e65e0fSDavid du Colombier p = (uchar*)md->base;
9490e65e0fSDavid du Colombier *(Memdata**)p = md;
9590e65e0fSDavid du Colombier p += sizeof(Memdata*);
9690e65e0fSDavid du Colombier
9790e65e0fSDavid du Colombier *(ulong*)p = getcallerpc(&r);
9890e65e0fSDavid du Colombier p += sizeof(ulong);
997dd7cddfSDavid du Colombier
1007dd7cddfSDavid du Colombier /* if this changes, memimagemove must change too */
10190e65e0fSDavid du Colombier md->bdata = p;
1027dd7cddfSDavid du Colombier md->allocd = 1;
1037dd7cddfSDavid du Colombier
1047dd7cddfSDavid du Colombier i = allocmemimaged(r, chan, md);
1057dd7cddfSDavid du Colombier if(i == nil){
1066a9fc400SDavid du Colombier poolfree(imagmem, md->base);
1077dd7cddfSDavid du Colombier free(md);
1087dd7cddfSDavid du Colombier return nil;
1097dd7cddfSDavid du Colombier }
1107dd7cddfSDavid du Colombier md->imref = i;
1117dd7cddfSDavid du Colombier return i;
1127dd7cddfSDavid du Colombier }
1137dd7cddfSDavid du Colombier
1147dd7cddfSDavid du Colombier void
freememimage(Memimage * i)1157dd7cddfSDavid du Colombier freememimage(Memimage *i)
1167dd7cddfSDavid du Colombier {
1177dd7cddfSDavid du Colombier if(i == nil)
1187dd7cddfSDavid du Colombier return;
1197dd7cddfSDavid du Colombier if(i->data->ref-- == 1 && i->data->allocd){
1207dd7cddfSDavid du Colombier if(i->data->base)
1217dd7cddfSDavid du Colombier poolfree(imagmem, i->data->base);
1227dd7cddfSDavid du Colombier free(i->data);
1237dd7cddfSDavid du Colombier }
1247dd7cddfSDavid du Colombier free(i);
1257dd7cddfSDavid du Colombier }
1267dd7cddfSDavid du Colombier
1277dd7cddfSDavid du Colombier /*
1287dd7cddfSDavid du Colombier * Wordaddr is deprecated.
1297dd7cddfSDavid du Colombier */
1307dd7cddfSDavid du Colombier ulong*
wordaddr(Memimage * i,Point p)1317dd7cddfSDavid du Colombier wordaddr(Memimage *i, Point p)
1327dd7cddfSDavid du Colombier {
133*8ccd4a63SDavid du Colombier return (ulong*) ((uintptr)byteaddr(i, p) & ~(sizeof(ulong)-1));
1347dd7cddfSDavid du Colombier }
1357dd7cddfSDavid du Colombier
1367dd7cddfSDavid du Colombier uchar*
byteaddr(Memimage * i,Point p)1377dd7cddfSDavid du Colombier byteaddr(Memimage *i, Point p)
1387dd7cddfSDavid du Colombier {
1397dd7cddfSDavid du Colombier uchar *a;
1407dd7cddfSDavid du Colombier
1417dd7cddfSDavid du Colombier a = i->data->bdata+i->zero+sizeof(ulong)*p.y*i->width;
1427dd7cddfSDavid du Colombier
1437dd7cddfSDavid du Colombier if(i->depth < 8){
1447dd7cddfSDavid du Colombier /*
1457dd7cddfSDavid du Colombier * We need to always round down,
1467dd7cddfSDavid du Colombier * but C rounds toward zero.
1477dd7cddfSDavid du Colombier */
1487dd7cddfSDavid du Colombier int np;
1497dd7cddfSDavid du Colombier np = 8/i->depth;
1507dd7cddfSDavid du Colombier if(p.x < 0)
1517dd7cddfSDavid du Colombier return a+(p.x-np+1)/np;
1527dd7cddfSDavid du Colombier else
1537dd7cddfSDavid du Colombier return a+p.x/np;
1547dd7cddfSDavid du Colombier }
1557dd7cddfSDavid du Colombier else
1567dd7cddfSDavid du Colombier return a+p.x*(i->depth/8);
1577dd7cddfSDavid du Colombier }
1587dd7cddfSDavid du Colombier
1597dd7cddfSDavid du Colombier int
memsetchan(Memimage * i,ulong chan)1607dd7cddfSDavid du Colombier memsetchan(Memimage *i, ulong chan)
1617dd7cddfSDavid du Colombier {
1627dd7cddfSDavid du Colombier int d;
1637dd7cddfSDavid du Colombier int t, j, k;
1647dd7cddfSDavid du Colombier ulong cc;
1657dd7cddfSDavid du Colombier int bytes;
1667dd7cddfSDavid du Colombier
1677dd7cddfSDavid du Colombier if((d = chantodepth(chan)) == 0) {
1687dd7cddfSDavid du Colombier werrstr("bad channel descriptor");
1697dd7cddfSDavid du Colombier return -1;
1707dd7cddfSDavid du Colombier }
1717dd7cddfSDavid du Colombier
1727dd7cddfSDavid du Colombier i->depth = d;
1737dd7cddfSDavid du Colombier i->chan = chan;
1747dd7cddfSDavid du Colombier i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes);
1757dd7cddfSDavid du Colombier bytes = 1;
1767dd7cddfSDavid du Colombier for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){
1777dd7cddfSDavid du Colombier t=TYPE(cc);
1787dd7cddfSDavid du Colombier if(t < 0 || t >= NChan){
1797dd7cddfSDavid du Colombier werrstr("bad channel string");
1807dd7cddfSDavid du Colombier return -1;
1817dd7cddfSDavid du Colombier }
1827dd7cddfSDavid du Colombier if(t == CGrey)
1837dd7cddfSDavid du Colombier i->flags |= Fgrey;
1847dd7cddfSDavid du Colombier if(t == CAlpha)
1857dd7cddfSDavid du Colombier i->flags |= Falpha;
1867dd7cddfSDavid du Colombier if(t == CMap && i->cmap == nil){
1877dd7cddfSDavid du Colombier i->cmap = memdefcmap;
1887dd7cddfSDavid du Colombier i->flags |= Fcmap;
1897dd7cddfSDavid du Colombier }
1907dd7cddfSDavid du Colombier
1917dd7cddfSDavid du Colombier i->shift[t] = j;
1927dd7cddfSDavid du Colombier i->mask[t] = (1<<NBITS(cc))-1;
1937dd7cddfSDavid du Colombier i->nbits[t] = NBITS(cc);
1947dd7cddfSDavid du Colombier if(NBITS(cc) != 8)
1957dd7cddfSDavid du Colombier bytes = 0;
1967dd7cddfSDavid du Colombier }
1977dd7cddfSDavid du Colombier i->nchan = k;
1987dd7cddfSDavid du Colombier if(bytes)
1997dd7cddfSDavid du Colombier i->flags |= Fbytes;
2007dd7cddfSDavid du Colombier return 0;
2017dd7cddfSDavid du Colombier }
202