alloc.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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[2];
  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. ulong l, nw;
  61. Memdata *md;
  62. Memimage *i;
  63. if((d = chantodepth(chan)) == 0) {
  64. werrstr("bad channel descriptor %.8lux", chan);
  65. return nil;
  66. }
  67. l = wordsperline(r, d);
  68. nw = l*Dy(r);
  69. md = malloc(sizeof(Memdata));
  70. if(md == nil)
  71. return nil;
  72. md->ref = 1;
  73. md->base = poolalloc(imagmem, (2+nw)*sizeof(ulong));
  74. if(md->base == nil){
  75. free(md);
  76. return nil;
  77. }
  78. md->base[0] = (ulong)md;
  79. md->base[1] = getcallerpc(&r);
  80. /* if this changes, memimagemove must change too */
  81. md->bdata = (uchar*)&md->base[2];
  82. md->allocd = 1;
  83. i = allocmemimaged(r, chan, md);
  84. if(i == nil){
  85. poolfree(imagmem, md->base);
  86. free(md);
  87. return nil;
  88. }
  89. md->imref = i;
  90. return i;
  91. }
  92. void
  93. freememimage(Memimage *i)
  94. {
  95. if(i == nil)
  96. return;
  97. if(i->data->ref-- == 1 && i->data->allocd){
  98. if(i->data->base)
  99. poolfree(imagmem, i->data->base);
  100. free(i->data);
  101. }
  102. free(i);
  103. }
  104. /*
  105. * Wordaddr is deprecated.
  106. */
  107. ulong*
  108. wordaddr(Memimage *i, Point p)
  109. {
  110. return (ulong*) ((ulong)byteaddr(i, p) & ~(sizeof(ulong)-1));
  111. }
  112. uchar*
  113. byteaddr(Memimage *i, Point p)
  114. {
  115. uchar *a;
  116. a = i->data->bdata+i->zero+sizeof(ulong)*p.y*i->width;
  117. if(i->depth < 8){
  118. /*
  119. * We need to always round down,
  120. * but C rounds toward zero.
  121. */
  122. int np;
  123. np = 8/i->depth;
  124. if(p.x < 0)
  125. return a+(p.x-np+1)/np;
  126. else
  127. return a+p.x/np;
  128. }
  129. else
  130. return a+p.x*(i->depth/8);
  131. }
  132. int
  133. memsetchan(Memimage *i, ulong chan)
  134. {
  135. int d;
  136. int t, j, k;
  137. ulong cc;
  138. int bytes;
  139. if((d = chantodepth(chan)) == 0) {
  140. werrstr("bad channel descriptor");
  141. return -1;
  142. }
  143. i->depth = d;
  144. i->chan = chan;
  145. i->flags &= ~(Fgrey|Falpha|Fcmap|Fbytes);
  146. bytes = 1;
  147. for(cc=chan, j=0, k=0; cc; j+=NBITS(cc), cc>>=8, k++){
  148. t=TYPE(cc);
  149. if(t < 0 || t >= NChan){
  150. werrstr("bad channel string");
  151. return -1;
  152. }
  153. if(t == CGrey)
  154. i->flags |= Fgrey;
  155. if(t == CAlpha)
  156. i->flags |= Falpha;
  157. if(t == CMap && i->cmap == nil){
  158. i->cmap = memdefcmap;
  159. i->flags |= Fcmap;
  160. }
  161. i->shift[t] = j;
  162. i->mask[t] = (1<<NBITS(cc))-1;
  163. i->nbits[t] = NBITS(cc);
  164. if(NBITS(cc) != 8)
  165. bytes = 0;
  166. }
  167. i->nchan = k;
  168. if(bytes)
  169. i->flags |= Fbytes;
  170. return 0;
  171. }