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