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