1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <memdraw.h> 5 #include <pool.h> 6 7 void 8 memimagemove(void *from, void *to) 9 { 10 Memdata *md; 11 12 md = *(Memdata**)to; 13 if(md->base != from){ 14 print("compacted data not right: #%p\n", md->base); 15 abort(); 16 } 17 md->base = to; 18 19 /* if allocmemimage changes this must change too */ 20 md->bdata = (uchar*)md->base+sizeof(Memdata*)+sizeof(ulong); 21 } 22 23 Memimage* 24 allocmemimaged(Rectangle r, ulong chan, Memdata *md) 25 { 26 int d; 27 ulong l; 28 Memimage *i; 29 30 if(Dx(r) <= 0 || Dy(r) <= 0){ 31 werrstr("bad rectangle %R", r); 32 return nil; 33 } 34 if((d = chantodepth(chan)) == 0) { 35 werrstr("bad channel descriptor %.8lux", chan); 36 return nil; 37 } 38 39 l = wordsperline(r, d); 40 41 i = mallocz(sizeof(Memimage), 1); 42 if(i == nil) 43 return nil; 44 45 i->data = md; 46 i->zero = sizeof(ulong)*l*r.min.y; 47 48 if(r.min.x >= 0) 49 i->zero += (r.min.x*d)/8; 50 else 51 i->zero -= (-r.min.x*d+7)/8; 52 i->zero = -i->zero; 53 i->width = l; 54 i->r = r; 55 i->clipr = r; 56 i->flags = 0; 57 i->layer = nil; 58 i->cmap = memdefcmap; 59 if(memsetchan(i, chan) < 0){ 60 free(i); 61 return nil; 62 } 63 return i; 64 } 65 66 Memimage* 67 allocmemimage(Rectangle r, ulong chan) 68 { 69 int d; 70 uchar *p; 71 ulong l, nw; 72 Memdata *md; 73 Memimage *i; 74 75 if((d = chantodepth(chan)) == 0) { 76 werrstr("bad channel descriptor %.8lux", chan); 77 return nil; 78 } 79 80 l = wordsperline(r, d); 81 nw = l*Dy(r); 82 md = malloc(sizeof(Memdata)); 83 if(md == nil) 84 return nil; 85 86 md->ref = 1; 87 md->base = poolalloc(imagmem, sizeof(Memdata*)+(1+nw)*sizeof(ulong)); 88 if(md->base == nil){ 89 free(md); 90 return nil; 91 } 92 93 p = (uchar*)md->base; 94 *(Memdata**)p = md; 95 p += sizeof(Memdata*); 96 97 *(ulong*)p = getcallerpc(&r); 98 p += sizeof(ulong); 99 100 /* if this changes, memimagemove must change too */ 101 md->bdata = p; 102 md->allocd = 1; 103 104 i = allocmemimaged(r, chan, md); 105 if(i == nil){ 106 poolfree(imagmem, md->base); 107 free(md); 108 return nil; 109 } 110 md->imref = i; 111 return i; 112 } 113 114 void 115 freememimage(Memimage *i) 116 { 117 if(i == nil) 118 return; 119 if(i->data->ref-- == 1 && i->data->allocd){ 120 if(i->data->base) 121 poolfree(imagmem, i->data->base); 122 free(i->data); 123 } 124 free(i); 125 } 126 127 /* 128 * Wordaddr is deprecated. 129 */ 130 ulong* 131 wordaddr(Memimage *i, Point p) 132 { 133 return (ulong*) ((uintptr)byteaddr(i, p) & ~(sizeof(ulong)-1)); 134 } 135 136 uchar* 137 byteaddr(Memimage *i, Point p) 138 { 139 uchar *a; 140 141 a = i->data->bdata+i->zero+sizeof(ulong)*p.y*i->width; 142 143 if(i->depth < 8){ 144 /* 145 * We need to always round down, 146 * but C rounds toward zero. 147 */ 148 int np; 149 np = 8/i->depth; 150 if(p.x < 0) 151 return a+(p.x-np+1)/np; 152 else 153 return a+p.x/np; 154 } 155 else 156 return a+p.x*(i->depth/8); 157 } 158 159 int 160 memsetchan(Memimage *i, ulong chan) 161 { 162 int d; 163 int t, j, k; 164 ulong cc; 165 int bytes; 166 167 if((d = chantodepth(chan)) == 0) { 168 werrstr("bad channel descriptor"); 169 return -1; 170 } 171 172 i->depth = d; 173 i->chan = chan; 174 i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes); 175 bytes = 1; 176 for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){ 177 t=TYPE(cc); 178 if(t < 0 || t >= NChan){ 179 werrstr("bad channel string"); 180 return -1; 181 } 182 if(t == CGrey) 183 i->flags |= Fgrey; 184 if(t == CAlpha) 185 i->flags |= Falpha; 186 if(t == CMap && i->cmap == nil){ 187 i->cmap = memdefcmap; 188 i->flags |= Fcmap; 189 } 190 191 i->shift[t] = j; 192 i->mask[t] = (1<<NBITS(cc))-1; 193 i->nbits[t] = NBITS(cc); 194 if(NBITS(cc) != 8) 195 bytes = 0; 196 } 197 i->nchan = k; 198 if(bytes) 199 i->flags |= Fbytes; 200 return 0; 201 } 202