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