alloc.c 3.3 KB

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